Удобный трединг в Javascript?

Приветствую.


На самом деле, речь не совсем о трединге. Да, в Javascript «чистого» трединга вроде как нету, но есть ещё webworkers, это я знаю, а здесь я хочу поднять вопрос о другом. Для начала я уточню, что конкретно я буду подразумевать под «тредингом».


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

setTimeout( myFunc, 10 );
doSomethingElse();



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


Самое загадочное в таком подходе — второй аргумент функции setTimeout(). Почему я сказал ей выполнить код через 10 милисекунд, а не сразу — через 0? Люди пишут (комменты), что setTimeout(fn, 0) часто работает дольше, чем setTimeout(fn, 10). И там же предлагается ещё более быстрый способ «заказать» асинхронное выполнение функции «прямо сейчас», с использованием postMessage.


Я решил немного поэкспериментировать с приведённым там кодом и сделать его чуть более удобным. Идея состоит в том, что прототипу объекта типа Function добавляется новый метод thread(), который запускает эту функцию асинхронно и форвардит ей все аргументы. Получилось примерно так:

(function() {
     var threads = [];
     var messageName = "start-thread";

     function thread(fn) {
         threads.push(fn);
         window.postMessage(messageName, "*");
     }

     function startThread(event) {
         if (event.source == window &&
             event.data == messageName) {
             event.stopPropagation();
             if (threads.length> 0) {
                 ( threads.shift() )();
             }
         }
     }

     window.addEventListener("message", startThread, true);

     Function.prototype.thread = function() {
         var args = arguments;
         var me = this;
         thread(
             function() {
                 me.apply( null, args );
             }
         );
     }

 })();


var doSomething = function(a, b) {
    alert( a + b );
}

// вызываем doSomething() асинхронно:
doSomething.thread( 2, 3 );



В общем, это практически точная копия кода по ссылке, плюс новый метод thread объектам типа Function.


И теперь внимание вопрос. Для того, чтобы метод thread был действительно удобным, нужно иметь возможность использовать его для методов объектов. То есть, каким-то образом в функцию thread нужно «протащить» информацию об объекте, в контексте которого мы обратились к методу. Использование замыкания напрочь испортит всю элегантность. Хочется пользоваться этим методом примерно так:

myObject.myMethod.thread( arg1, arg2 );


и в результате такого вызова метод myMethod должен вызваться асинхронно в контексте объекта myObject, то есть должно произойти

myObject.myMethod.apply( myObject, [ arg1, arg2 ] );



Возможно ли это?
  • Вопрос задан
  • 2899 просмотров
Пригласить эксперта
Ответы на вопрос 3
barmaley_exe
@barmaley_exe
Можно сделать обертку для замыканий, чтобы не портить код.
Только вот реализовать в виде
myObject.myMethod.thread( arg1, arg2 );
вряд ли получится, скорее
myObject.thread( 'myMethod', arg1, arg2 );
Ответ написан
@kmike
Собвственно, в mootools это все реализовано, и с биндингом, и с передачей аргументов. Можно или посмотреть, как, или просто использовать mootools.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы