您想要的是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 访问权限(用于 Deferreds)。
然后你就可以为所有的 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 版本中受支持)