2 回答
TA贡献1895条经验 获得超7个赞
我认为 async 主要用于 api 调用(?)
有两个与该词相关的不同概念async
:
async/await
函数以同步方式接收 Promises 结果的语法糖真正的异步行为 XHR api 调用、延迟执行、事件处理
async/await
function 不会自动使您的函数执行异步。
const foo = async (i) => { console.log('foo running', i); return i == 0 ? 42 : await foo(i-1); };
console.log('foo before')
foo(5)
.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 42
JavaScript 是单线程的,所有并发任务必须分成异步块,以便其他任务有机会工作。
因此,您应该将同步循环拆分为许多异步部分,以免被冻结。
例如(我减少参数以便没有太多等待时间):
async function calcX() {
let x = 0;
function iteration(i) {
x += (i * 99999);
if (++i >= 10000) return Promise.resolve(x);
return new Promise((resolve) => {
setTimeout(() => iteration(i).then(resolve), 0);
// or requestAnimationFrame
});
}
return await iteration(1);
}
const start = Date.now();
calcX()
.then(x => console.log(x, Date.now() - start), err => console.error(err));
// 4999450005000 42465
如果将每次迭代都放入事件循环中,它可能会太慢。所以你可以通过批处理它们来优化它(参见@Steve的答案)
或者使用 WebWorker 来完成繁重的同步任务
TA贡献1810条经验 获得超5个赞
您可以通过检查是否已经过了设定的时间,然后稍后返回该函数,将长时间运行的同步函数转换为异步函数(在此示例中通过 实现)setTimeout:
var lastBreak = Date.now()
function takeABreak() {
return new Promise(resolve=>setTimeout(resolve));
}
async function maybeTakeABreak() {
if (Date.now() - 17 > lastBreak) {
lastBreak = Date.now();
await takeABreak();
}
}
async function myLongLoop() {
let x = 0;
for (let i = 1; i < 100000000000000; i++) {
await maybeTakeABreak();
x += (i * 99999);
if (!(i%1000000)) {
console.log(i);
// alternatively you could run `await takeABreak();` here
}
}
return x;
}
myLongLoop().then(x=>console.log(x));
添加回答
举报