Javascript - 等待超长循环的正确方法?

也许这是一个 async/await 情况,但我认为 async 主要用于 api 调用(?)


你如何等待一个很长的循环完成,就像这样:


let x;

for (i = 1, i < 10000000000000000, i++) {

  x += (i * 99999);

}


console.log(x);


天涯尽头无女友
浏览 151回答 2
2回答

人到中年有点甜

我认为 async 主要用于 api 调用(?)有两个与该词相关的不同概念async:async/await函数以同步方式接收 Promises 结果的语法糖真正的异步行为 XHR api 调用、延迟执行、事件处理async/awaitfunction 不会自动使您的函数执行异步。const foo = async (i) => { console.log('foo running', i); return i == 0 ? 42 : await foo(i-1); };console.log('foo before')foo(5)&nbsp; .then(x => console.log('foo', x))console.log('foo after')// foo before// foo running 5// foo running 4// foo running 3// foo running 2// foo running 1// foo running 0// foo after// foo 42JavaScript 是单线程的,所有并发任务必须分成异步块,以便其他任务有机会工作。因此,您应该将同步循环拆分为许多异步部分,以免被冻结。例如(我减少参数以便没有太多等待时间):async function calcX() {&nbsp; let x = 0;&nbsp; function iteration(i) {&nbsp; &nbsp; x += (i * 99999);&nbsp; &nbsp; if (++i >= 10000) return Promise.resolve(x);&nbsp; &nbsp; return new Promise((resolve) => {&nbsp; &nbsp; &nbsp; setTimeout(() => iteration(i).then(resolve), 0);&nbsp; &nbsp; &nbsp; // or requestAnimationFrame&nbsp; &nbsp; });&nbsp; }&nbsp; return await iteration(1);}const start = Date.now();calcX()&nbsp; .then(x => console.log(x, Date.now() - start), err => console.error(err));// 4999450005000 42465如果将每次迭代都放入事件循环中,它可能会太慢。所以你可以通过批处理它们来优化它(参见@Steve的答案)或者使用 WebWorker 来完成繁重的同步任务

森栏

您可以通过检查是否已经过了设定的时间,然后稍后返回该函数,将长时间运行的同步函数转换为异步函数(在此示例中通过 实现)setTimeout:var lastBreak = Date.now()function takeABreak() {&nbsp; &nbsp; return new Promise(resolve=>setTimeout(resolve));}async function maybeTakeABreak() {&nbsp; &nbsp; if (Date.now() - 17 > lastBreak) {&nbsp; &nbsp; &nbsp; &nbsp; lastBreak = Date.now();&nbsp; &nbsp; &nbsp; &nbsp; await takeABreak();&nbsp; &nbsp; }}async function myLongLoop() {&nbsp; &nbsp; let x = 0;&nbsp; &nbsp; for (let i = 1; i < 100000000000000; i++) {&nbsp; &nbsp; &nbsp; &nbsp;await maybeTakeABreak();&nbsp; &nbsp; &nbsp; &nbsp;x += (i * 99999);&nbsp; &nbsp; &nbsp; &nbsp;if (!(i%1000000)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(i);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // alternatively you could run `await takeABreak();` here&nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; }&nbsp; &nbsp; return x;}myLongLoop().then(x=>console.log(x));
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript