首先,重要的是要提到 JavaScript 是完全单线程的。模拟多线程真的不是要走的路。依赖事件循环会好得多。
如前所述,可以使用网络工作者,但他们并没有真正的跨浏览器合规性,所以我将忽略网络工作者。此外,您不能对 Web 工作者进行任何 DOM 操作。
我想说看看node.js来推理为什么事件循环是多线程的一个很好的替代方案。我相信他很好地解释了为什么它在这个视频中是一个很好的选择。
因此,与其拥有一组函数并对其进行迭代,不如创建一个事件并将一组函数绑定到它们并触发所述事件。在主干.js中可以找到一个非常轻量级的事件实现。
你不能只暂停 JavaScript 中的一个线程,因为只有一个。如果函数中没有点,就无法暂停或恢复函数。
只有一种方法可以模仿这一点。编写一个 JavaScript 解析器,将您精心构建的 JavaScript 分开,并构建一个允许您暂停和恢复 JavaScript 的系统。
以这个函数为例
function(i) {
j = i + 1;
console.log(j);
return foo(j);
}
并将其转换为
var bar = function(i) {
var r = {};
var j = i + 1;
var f = function() {
console.log(j);
var g = function() {
return foo(j);
};
onNext(g, arguments.callee, this, r);
};
onNext(f, arguments.callee, this);
return r;
}
您将需要使用.suspend
和扩展功能.resume
Function.prototype.suspend = function() {
this.__suspended = true;
}
Function.prototype.resume = function() {
this.__suspended = false;
}
function onNext(callback, function, context, returnObj) {
if (!function.__suspended) {
var cb = function() {
Backbone.Events.unbind("run", cb);
returnObj.r = callback.call(this);
}
Backbone.Events.bind("run", cb);
}
}
setInterval(function() {
Backbone.Events.trigger("run");
}, 5);
您还必须将所有引用替换var a = b()
为
callFunctionAsync(b, context, args, function(return) {
var a = return;
...
});
我会把实施留给你。现在所有函数都返回一个对象r
,只有当r.r
设置为一个值时它才会“返回”。r.r
因此,只需通过检查是否已设置以及是否触发了函数异步回调来检查事件循环是否已“返回” 。
嘿,看看我们有什么。通过在事件循环中运行线程来模拟线程。在代码中本地使用事件循环比通过它模拟线程要好得多。
当您再次绕过事件循环时,基本上让您的函数运行其代码的下一行。并检查在您绕过事件循环时特定的“功能”是否被暂停或恢复。
为了简洁起见,我没有实现将函数的返回冒泡返回到“函数”。这不应该太难模仿。
要么直接使用事件循环,要么使用假线程方法,并让编译器编译你的代码,这样你在编码时它就不会看起来很可怕。
如果你造成死锁,祝你好运。