我一直致力于在JavaScript中实现一个非常复杂的系统,需要模拟多线程进程等。在真正的多线程进程(例如内核线程)中,可以通过上下文切换在线程之间切换。这是有效的,因为您可以存储当前进程的程序计数器并注册到临时结构,还原程序计数器并注册其他进程,然后在上一过程中从中断处继续。
我很好奇是否可以在JavaScript中使用类似的东西。我目前不知道这样做,所以一直在使用协作式多任务设计系统。特别是,我想在多线程模拟器中运行的任何“函数”被分成函数的数组。为了执行“函数”,我遍历函数数组,按顺序执行每个函数,同时保持接下来执行哪个函数的“程序计数器”。这允许我通过调用数组中的一个函数来模拟上下文切换,等待函数返回,然后切换到需要执行的其他函数数组。
我目前的方法有效,但在这个系统中编写代码很困难。每个函数必须具体指明它何时可以被中断,并且因为数组中的函数都是分开的,所以在函数的不同部分之间传递数据的逻辑是复杂的。我希望能够更接近先发制人的多任务工作。
我的问题是:是否可以通过外部来源暂停和恢复任意JavaScript功能?
答案 0 :(得分:4)
答案 1 :(得分:3)
首先,重要的是要提到JavaScript是完全单线程的。模拟多线程真的不是可行的方法。你依靠eventloops好多了。
如前所述,可以使用网络工作者,但实际上并没有针对他们的跨浏览器合规性,所以我会忽略网络工作者。此外,您无法对Web worker进行任何DOM操作。
我想说看node.js来推断为什么事件循环是多线程的一个很好的替代品。我相信他很清楚为什么它在这个video中是一个很好的选择。
因此,有了一个函数数组并迭代它们,您可以创建一个事件并将一组函数绑定到它们并触发所述事件。可以在backbone.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
以及是否已触发函数异步回调来检查事件循环是否已“返回”。
当你再次绕过事件循环时,基本上让你的函数运行它的代码的下一行。当你绕过eventloop时,检查特定的“功能”是否被暂停或恢复。
为了简洁起见,我没有实现将函数返回冒泡回“函数”。这不应该太难模仿。
直接使用事件循环或使用伪线程方法并获取编译器来编译代码,以便在编码时看起来不可思议。
如果你造成死锁,祝你好运。