Мне интересно - как еще можно добиться многопоточности в JavaScript?Любые другие важные методы?
Вы можете преобразовать свой код в код JavaScript, который не имеет явных циклов или прямых вызовов функций, вместо этого код делится на небольшие единицы извыполнение, которое управляется механизмом потоков.В моем примере кода я показываю, как должна быть преобразована функция с циклами, но я упустил механизм для вызова функций просто для простоты примера.
Процесс преобразования в основном работает путем расщепления код в точках деления.Эти точки деления являются вызовами функций и циклами (как показано выше).В этом примере я использовал объекты и ключи, но на JavaScript-движках браузера может быть намного проще, если unit хранит stack как переменную объекта (т.е. хранится с использованием this.foo = bar
вместо stack["foo"] = bar
).
Например, следующий код:
// 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};
}
}