我的想法是。 我的工人数量有限。 这些工人必须做一些工作。 当工人完成工作时,他必须完成其他工作,直到完成所有工作。
我写这段代码:
function createWorker(num){
this.num = num;
this.Run = (job) => (
new Promise(
(resolve, reject) => {
setTimeout(() => { resolve({worker: this, num: this.num, job: job}); }, 5000);
}
)
);
}
function Processing(maxWorkers, jobs){
this.Workers = [];
this.Jobs = jobs;
this.Go = () => {
return new Promise(
(resolve, reject) => {
while(true){
let worker = this.Workers.pop();
if (!worker) continue;
let job = this.Jobs.pop();
if (!job) break;
worker.Run(job)
.then(
res => {
console.log(res);
this.Workers.push(res.worker);
}
);
}
resolve("Complete");
}
)
}
for(var i = 0; i < maxWorkers; i++){
this.Workers.push(new createWorker(i));
}
}
let jobs = ['a', 'b', 'c', 'd', 'e'];
let proc = new Processing(3, jobs);
proc.Go()
.then(
res => {
console.log(res);
}
);
一项工作的代码运作良好
let worker = new createWorker(1);
worker.Run("a")
.then(
res => {
console.log("Complete " + res.num + " job " + res.job);
}
);
为什么我的代码不起作用?它看起来像冻结。
答案 0 :(得分:2)
在javascript中,只有在没有剩余的javascript代码需要处理时才会处理事件循环。这是因为javascript是单线程的。因此,事件循环不能与javascript代码并行处理。解释器的基本结构是:
execute javascript code -----------> process event loop
^ |
| |
'---------------------------------'
鉴于此,javascript代码中的无限循环意味着永远不会处理事件循环。
那么这与网络工作者有什么关系呢?好吧,网络工作者在他们自己的线程中执行,因此他们将与无限循环并行运行。但是,我们从网络工作者那里获取数据的方式是:
worker.Run(job).then()
这需要运行事件循环。因此,虽然工作者可以与无限循环并行运行,但无限循环和工作者之间的通信将不会被处理,因为您不会让解释器有机会处理事件循环。
您无法在javascript应用中使用无限循环。
解决方案是使用事件循环。如果您想要定期异步循环,请使用setTimeout()
或setInterval()
。或者通过“递归”循环在.then()
内再次调用该函数,直到你用完了要处理的东西。