То, что вы хотите, это комбинация yield
и Deferreds
(например, jquery
).
Это иногда называют псевдо-нитью, легкой нитью или зеленой нитью. И вы можете делать именно то, что вы хотите с ними в JavaScript> 1,7. А вот как:
Сначала вам нужно будет включить этот код:
$$ = function (generator) {
var d = $.Deferred();
var iter;
var recall = function() {
try {var def = iter.send.apply(iter, arguments);} catch(e) {
if (e instanceof StopIteration) {d.resolve(); return;}
if (e instanceof ReturnValueException) {
d.resolve(e.retval); return
};
throw e;
};
$.when(def).then(recall); // close the loop !
};
return function(arguments) {
iter = generator.apply(generator, arguments);
var def = iter.next(); // init iterator
$.when(def).then(recall); // loop in all yields
return d.promise(); // return a deferred
}
}
ReturnValueException = function (r) {this.retval = r; return this; };
Return = function (retval) {throw new ReturnValueException(retval);};
И, конечно, вызовите код jquery, чтобы получить $
доступ JQuery (для отложенных).
Тогда вы сможете один раз определить функцию Sleep:
function Sleep(time) {
var def = $.Deferred();
setTimeout(function() {def.resolve();}, time);
return def.promise();
}
И используйте его (вместе с другой функцией, которая может занять некоторое время):
// Sample function that take 3 seconds to execute
fakeAjaxCall = $$(function () {
yield (Sleep(3000));
Return("AJAX OK");
});
А еще есть полнофункциональная демонстрационная функция:
function log(msg) {$('<div>'+msg+'</div>').appendTo($("#log")); }
demoFunction = $$(function (arg1, arg2) {
var args = [].splice.call(arguments,0);
log("Launched, arguments: " + args.join(", "));
log("before sleep for 3secs...");
yield (Sleep(3000));
log("after sleep for 3secs.");
log("before call of fake AjaxCall...");
ajaxAnswer = yield (fakeAjaxCall());
log("after call of fake AjaxCall, answer:" + ajaxAnswer);
// You cannot use return, You'll have to use this special return
// function to return a value
log("returning 'OK'.");
Return("OK");
log("should not see this.");
});
Как видите, синтаксис немного отличается:
Помните:
- любая функция, которая должна иметь эти функции, должна быть заключена в
$$(myFunc)
$$
поймает любое полученное значение из вашей функции и возобновит его только тогда, когда
Приведенная стоимость закончилась для расчета. Если это не побежденный, это будет работать
также.
- Используйте «Return» для возврата значения.
- Это будет работать только с Javascript 1.7 (который поддерживается в более новой версии Firefox)