Javascript.RU

Многопоточный яваскрипт

Яваскрипт - однопоточный язык программирования. однако, в нём есть поддержка отложенного выполнения, когда мы устанавливаем обработчик события timeout и выходим из программы.

При этом можно повесить несколько обработчиков, образующих конкурентную очередь выполнения.

Эта их особенность и позволяет реализовать многопоточность в текущих версиях яваскрипта.

  1. Можно выполнять долгие вычисления или анимацию, не вешая при этом пользовательский интерфейс.
  2. Следствие из (1) - у нас нет ограничения на время выполнения.
  3. Каждый процесс является "истинным объектом" с очередью сообщений, рабочим пространством и независимостью от работоспособности других объектов.

из-за особеностей реализации (через таймер) суммарное время вполнения программы может сильно замедлитья, ибо 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' и сразу переходит к выполнению первой итерации. внутри итерации выполняются некоторые действия и происходит проверка условия окончания цикла. если ещё не пора - повторяем итерацию, если пора - выполняем завершение процесса и переводим процесс в режим ожидания.

основное отличие в том, что во время выполнения процесс продолжает принимать сообщения от сторонних процессов и, например, может принять решение о досрочном завершении цикла или какого-либо иного изменения состояния. при этом в разных состояниях процесс принимает различные сообщения. например, его нельзя остановить, пока он не запущен, ибо это не имеет никакого смысла.

актуальное применение такого подхода - различные виды анимации, когда в связи с действиями пользователя требуется в срочном порядке прекратить одну анимацию и приступить к другой.

на этом пока всё. предложенные выше примеры, конечно, ещё нуждаются в доработке. например, неплохо было бы реализовать декоратор не генерирующий по анонимной функции на каждый вызов. также неплохо было бы продумать механизм разграничения внутренних сообщений и внешних. ещё нужно написать метод форканья процесса. ну и, наконец, нужно написать примеры типовых паттернов использования такой многопоточности (два из них - отложенное выполнение и цикл - уже рассмотрены).

+2

Автор: Dmitry A. Soshnikov, дата: 25 апреля, 2008 - 23:48
#permalink

тоже далеко не новая идея, но полезная и интересная


Автор: Гость (не зарегистрирован), дата: 19 декабря, 2008 - 01:08
#permalink

не плохая статейка. помогло


Автор: hudson (не зарегистрирован), дата: 6 февраля, 2010 - 21:25
#permalink

Эм. Пример с применением конструктора процессов не работает. Выводит "0" и все. Что я делаю не так?


Автор: Iodisbuhsob (не зарегистрирован), дата: 4 января, 2011 - 15:43
#permalink

У нас вы сможите скачать, самое актуальное и новое
Бесплатно!


Автор: ucoz вопросы (не зарегистрирован), дата: 22 января, 2011 - 22:28
#permalink

Прикольный болг, много нашел статей нужных, в которых подробно все описано, спасибо


Автор: Лечение в Израиле (не зарегистрирован), дата: 23 января, 2011 - 10:56
#permalink

не много статей, советую регулярно добавять, а так в общем блог интересный


Автор: RUVATA, дата: 15 августа, 2011 - 10:31
#permalink

Где можно найти рефференс по методу "process" ?


Автор: Гость (не зарегистрирован), дата: 31 августа, 2011 - 13:07
#permalink

Код метода перед Вами.
Он не столь велик, чтобы для его освоения требовался отдельный мануал.


Отправить комментарий

Приветствуются комментарии:
  • Полезные.
  • Дополняющие прочитанное.
  • Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
    Для остальных вопросов и обсуждений есть форум.
P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.
Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешены HTML-таги: <strike> <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <u> <i> <b> <pre> <img> <abbr> <blockquote> <h1> <h2> <h3> <h4> <h5> <p> <div> <span> <sub> <sup>
  • Строки и параграфы переносятся автоматически.
  • Текстовые смайлы будут заменены на графические.

Подробнее о форматировании

CAPTCHA
Антиспам
4 + 1 =
Введите результат. Например, для 1+3, введите 4.
 
Поиск по сайту
Другие записи этого автора
tenshi
Реклама
Содержание

Учебник javascript

Основные элементы языка

Сундучок с инструментами

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Популярные таги
Последние комментарии
Последние темы на форуме
Forum