Многопоточный яваскрипт
Яваскрипт - однопоточный язык программирования. однако, в нём есть поддержка отложенного выполнения, когда мы устанавливаем обработчик события timeout и выходим из программы.
При этом можно повесить несколько обработчиков, образующих конкурентную очередь выполнения.
Эта их особенность и позволяет реализовать многопоточность в текущих версиях яваскрипта.
-
Можно выполнять долгие вычисления или анимацию, не вешая при этом пользовательский интерфейс.
- Следствие из (1) - у нас нет ограничения на время выполнения.
- Каждый процесс является "истинным объектом" с очередью сообщений, рабочим пространством и независимостью от работоспособности других объектов.
из-за особеностей реализации (через таймер) суммарное время вполнения программы может сильно замедлитья, ибо setTimeout приводит к ощутимой задержке между сообщениями. однако, благодаря этому, браузер успевает отреагировать на активность пользователя и произвести все перерасчёты, связанные с ДОМ-ом, что бывает необходимо в некоторых случаях (например - native selectors в ИЕ). также мы получаем возможность производить безболезненно тяжёлые вычисления (например, сортировку большой таблицы).
что ж, ближе к делу...
Function.prototype.process= function( state ){
var process= function( ){
var args= arguments;
var self= arguments.callee;
setTimeout( function( ){
self.handler.apply( self, args );
}, 0 )
}
for( var i in state ) process[ i ]= state[ i ];
process.handler= this;
return process;
}
суть его такова: любую функцию можно превратить в процесс, вызвав её метод process. в качестве параметра ему передаётся объект, полями которого инициируется процесс. фактически, процесс является декоратором для функции, реализующиим её отложенное выполнение.
var printer= function( data ){
document.write( data + ' ' );
}
for( var i= 0; i<100; i++ ){
printer( i );
document.write( '| ' );
}
Если выполнить этот код, то будут выведены числа от 0 до 99, разделённые вертикальной чертой. то есть, выполнение нашего кода приостанавливается на время выполнения функции print.
Однако, если мы декорируем эту функцию с помощью метода process:
printer= printer.process();
for( var i= 0; i<100; i++ ){
printer( i );
document.write( '| ' );
}
, то будет выведена сначала сотня вертикальных черт, а потом уже сотня чисел. то есть, мы передали функции сообщение и не дожидаясь завершения её выполнения, работаем дальше.
но далеко не всегда нужно полностью выйти из режима выполнения полностью - зачастую требуется временно приостановить выполнение с целью последующего возобновления с того же места. для этих целей есть смысл ввести такие понятия, как "состояние процесса" и "передача сообщений". и поможет нам в реализации всего этого замечательная конструкция switch-case:
var business= function( input ){
switch( input.message ){
case 'start':
if( this.state !== 'wait' ) return this( input );
this.body= document.getElementsByTagName( 'body' )[0];
this.body.innerHTML+= '[business started] ';
this.state= 'run';
this.iteration= 0;
case 'next':
if( this.state !== 'run' ) return;
this.body.innerHTML+= this.iteration + ' ';
if( ++this.iteration < 100 ) return this({ message: 'next' });
case 'finish':
if( this.state !== 'run' ) return;
this.body.innerHTML+= '[business stopped] ';
this.state= 'wait';
return;
}
}.process({ state: 'wait' })
business({ message: 'start' });
мы создаём процесс, и инициируем его состояние строкой 'wait'. в этом режиме процесс висит и тупо ждёт комманды начать выполнение. как только к нему приходит комманда стартануть (последняя строчка), он инициализирует некоторые свои переменные ( body, iteration ), меняет состояние на 'run' и сразу переходит к выполнению первой итерации. внутри итерации выполняются некоторые действия и происходит проверка условия окончания цикла. если ещё не пора - повторяем итерацию, если пора - выполняем завершение процесса и переводим процесс в режим ожидания.
основное отличие в том, что во время выполнения процесс продолжает принимать сообщения от сторонних процессов и, например, может принять решение о досрочном завершении цикла или какого-либо иного изменения состояния. при этом в разных состояниях процесс принимает различные сообщения. например, его нельзя остановить, пока он не запущен, ибо это не имеет никакого смысла.
актуальное применение такого подхода - различные виды анимации, когда в связи с действиями пользователя требуется в срочном порядке прекратить одну анимацию и приступить к другой.
на этом пока всё. предложенные выше примеры, конечно, ещё нуждаются в доработке. например, неплохо было бы реализовать декоратор не генерирующий по анонимной функции на каждый вызов. также неплохо было бы продумать механизм разграничения внутренних сообщений и внешних. ещё нужно написать метод форканья процесса. ну и, наконец, нужно написать примеры типовых паттернов использования такой многопоточности (два из них - отложенное выполнение и цикл - уже рассмотрены).
|
тоже далеко не новая идея, но полезная и интересная
не плохая статейка. помогло
Эм. Пример с применением конструктора процессов не работает. Выводит "0" и все. Что я делаю не так?
У нас вы сможите скачать, самое актуальное и новое
Бесплатно!
Прикольный болг, много нашел статей нужных, в которых подробно все описано, спасибо
не много статей, советую регулярно добавять, а так в общем блог интересный
Где можно найти рефференс по методу "process" ?
Код метода перед Вами.
Он не столь велик, чтобы для его освоения требовался отдельный мануал.
предоставленная информация очень полезна, у меня есть аналогичная проблема, и я изучаю ее, word finder
Roksa słupsk
Cleo roksa
Roksa rabka zdrój
Roksa lubelskie
willcraft shop
it seems like there is still room for improvement in terms of optimizing the decorator and handling internal and external messages. On a different note, have you ever tried discussing these concepts with random people on omegle chat?
Отправить комментарий
Приветствуются комментарии:Для остальных вопросов и обсуждений есть форум.