好吧 - 所以我已经写了这个并且它按照我想要的方式工作,我只是不明白它是如何工作的/为什么它按照它的方式工作。
有人可以解释一下我在这里缺少什么吗?
这是代码:
const crypto = require('crypto');
class ProcessController extends AbortController {
timeouts = new Map();
sleep(ms) {
const id = crypto.randomBytes(8).toString('hex');
return new Promise((resolve) => {
this.timeouts.set(id, setTimeout(() => {
this.timeouts.delete(id);
resolve();
}, ms))
})
}
abort() {
super.abort();
for (const timeout of this.timeouts.values()) {
clearTimeout(timeout);
}
// not really necessary as not reusable but be tidy
this.timeouts.clear();
}
}
async function meLoop(controller) {
const { signal } = controller;
while (!signal.aborted) {
console.log("START OF LOOP. Uptime:", Math.floor(process.uptime()));
await controller.sleep(5 * 1000);
console.log('END OF LOOP');
}
console.log("BEYOND LOOP. Uptime:", process.uptime());
}
async function main() {
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const controller = new ProcessController();
meLoop(controller);
await sleep(23 * 1000);
controller.abort();
console.log("END. Uptime:", process.uptime());
}
main();
结果如下:
> node testBreakSleep.js
START OF LOOP. Uptime: 0
END OF LOOP
START OF LOOP. Uptime: 5
END OF LOOP
START OF LOOP. Uptime: 10
END OF LOOP
START OF LOOP. Uptime: 15
END OF LOOP
START OF LOOP. Uptime: 20
END. Uptime: 23.044878139
基本上,这是一个可中止的循环。我的理解是,在 while 循环期间,其中的任何内容都应该在再次评估 while 之前运行完成,因为 Javascript 是单线程的。
但是,我不明白的是,当调用
abort()
并且清除 setTimeout
时,它只是退出而不是完成循环?我不明白承诺会发生什么?它无法解析,并且永远不会到达循环末尾(这对我来说有好处)
有人可以解释一下吗?
编辑 - 我想我应该提到,如果我注释掉
clearTimeout
函数中的 abort()
,Node 会一直挂起,直到承诺解决。
> node testBreakSleep.js
START OF LOOP. Uptime: 0
END OF LOOP
START OF LOOP. Uptime: 5
END OF LOOP
START OF LOOP. Uptime: 10
END OF LOOP
START OF LOOP. Uptime: 15
END OF LOOP
START OF LOOP. Uptime: 20
END. Uptime: 23.037329278
END OF LOOP
BEYOND LOOP. Uptime: 25.041987186
谢谢
当
meLoop()
来电时
await controller.sleep(5 * 1000);
该函数将暂停,直到
sleep()
中的超时结束并调用 resolve()
。
当您清除
ProcessController.abort()
中的超时时,它永远不会调用 resolve()
,因此 await
语句永远不会完成,循环将永远挂起。