我想知道 - 你还能如何在 JavaScript 中实现多线程?还有什么重要的方法吗?
您可以将代码转换为没有任何显式循环或直接函数调用的 JavaScript 代码,而是将代码划分为由线程引擎管理的小执行单元。在我的示例代码中,我展示了如何转换带有循环的函数,但我省略了函数调用的机制,只是为了保持示例简单。
转换过程基本上是通过在分割点拆分代码来实现的。这些划分点是函数调用和循环(如上所示)。在示例中,我使用了对象和键,但如果单元将堆栈存储为对象变量(即使用this.foo = bar
而不是存储stack["foo"] = bar
),则在浏览器的 JavaScript 引擎上可能会容易得多。
例如下面的代码:
// Phoney method purely to demonstrate structure
function Foo() {
var i,
sum = 0,
accumulator_list = [],
accumulator_modulus = [],
kMaxAccumulatorCount = 100;
// Calculate accumulations
for(i = 0; i < kMaxAccumulatorCount; ++i) {
current_accumulator = GetNextAccumulator()
accumulator_list[i] = current_accumulator;
sum = sum + current_accumulator;
}
// Calculate accumulator modulus
for(i = 0; i < kMaxAccumulatorCount; ++i) {
current_accumulator = accumulator_list[i];
accumulator_modulus[i] = current_accumulator % kMaxAccumulatorCount;
}
}
...变成这样的东西:
function Foo_A(caller,stack) {
var stack = {};
stack["i"] = undefined;
stack["sum"] = 0;
stack["accumulator_list"] = [];
stack["accumulator_modulus"] = [];
stack["kMaxAccumulatorCount"] = 100;
stack["i"] = 0;
return {caller: caller, stack: stack, next=Foo_B};
}
function Foo_B(caller, stack) {
stack["current_accumulator"] = GetNextAccumulator();
stack["accumulator_list"][stack["i"]] = stack["current_accumulator"];
stack["sum"] = stack["sum"] + stack["current_accumulator"];
// For-loop condition satisfied ?
if(stack["i"] < stack["kMaxAccumulatorCount"]) {
++stack["i"];
return {caller: caller, stack: stack, next:Foo_B};
} else {
// Initialise the next for loop.
stack["i"] = 0;
return {caller: caller, stack: stack, next:Foo_C};
}
}
function Foo_C(caller, stack) {
stack["current_accumulator"] = stack["current_accumulator"][stack["i"]];
stack["accumulator_modulus"][stack["i"]] = stack["current_accumulator"] % stack["kMaxAccumulatorCount"];
// For-loop condition satisfied ?
if(stack["i"] < stack["kMaxAccumulatorCount"]) {
++stack["i"];
return {caller: caller, stack: stack, next:Foo_C};
} else {
// Function has finished so the next will be null. When the thread-engine sees this it simulates the behaviour of a return, pops its virtual stack and returns execution to the caller
return {caller: caller, stack: stack, next:null};
}
}