Pas*_*cal 2 javascript asynchronous settimeout async-await
我有一个async,await和setTimeout()的问题.我想,我使用异步函数来处理慢进程.所以我尝试了一个大循环.在我的计算机上,运行以下代码需要几秒钟:
function slowFunction() {
return new Promise(resolve => {
setTimeout(() => {
for (let i = 0; i < 4000000000; i++) {};
resolve('Ready at ' + new Date().toLocaleTimeString('de'));
}, 0);
});
};
console.log('Start: ' + new Date().toLocaleTimeString('de'));
(async () => {
console.log('Call slow function.');
console.log(await slowFunction());
})();
console.log('There is no need to wait for the slow function: ' + new Date().toLocaleTimeString('de'));
Run Code Online (Sandbox Code Playgroud)
输出是:
Start: 16:39:20
Call slow function.
There is no need to wait for the slow function: 16:39:20
Ready at 16:39:23
Run Code Online (Sandbox Code Playgroud)
现在的问题是:下一个代码有什么区别:
function slowFunction() {
return new Promise(resolve => {
for (let i = 0; i < 4000000000; i++) {};
resolve('Ready at ' + new Date().toLocaleTimeString('de'));
});
};
console.log('Start: ' + new Date().toLocaleTimeString('de'));
(async () => {
console.log('Call slow function.');
console.log(await slowFunction());
})();
console.log('There is no need to wait for the slow function: ' + new Date().toLocaleTimeString('de'));
Run Code Online (Sandbox Code Playgroud)
输出是:
Start: 16:39:20
Call slow function.
There is no need to wait for the slow function: 16:39:23
Ready at 16:39:23
Run Code Online (Sandbox Code Playgroud)
从第一个例子看,它看起来像异步.通过第二个例子,函数等待循环结束.
我是否必须使用setTimeout或者代码中是否有错误或者我错了?在这两种情况下,解决方案都是大循环的背后.
async和await的大多数示例都使用了setTimeout,但我认为,它只是模拟一个中断.
感谢您的帮助.
最好迎接Pascal
Promise和async函数不会将您的代码卸载到另一个线程.如果你想将这个长时间运行的进程从主线程移开,在浏览器上查看web worker,在Node.js上查看子进程.
Promise和async函数(这只是创建和使用promises的语法)不会将您的处理移动到任何其他线程,它仍然发生在您启动该进程的同一个线程上.在只有他们做的事情是确保then和catch回调异步调用.它们不会使您的代码异步(除了那一件事,确保回调异步发生).
所以你的第一个块setTimeout只使用设置超时,返回一个promise,然后当超时到期时,它会在你的慢速运行进程执行时阻塞主线程.这只是在阻塞发生一点点时发生变化,它不会改变阻塞的事实.
您可以在此处查看该效果,注意计数器在长时间运行的进程发生时如何暂停:
function slowFunction() {
return new Promise(resolve => {
setTimeout(() => {
const stop = Date.now() + 2000;
while (Date.now() < stop) {
// busy wait (obviously, never really do this)
}
}, 1000);
});
};
console.log("before slowFunction");
slowFunction()
.then(() => {
console.log("then handler on slowFunction's promise");
})
.catch(console.error);
console.log("after slowFunction");
let counter = 0;
const timer = setInterval(() => {
console.log(++counter);
}, 100);
setTimeout(() => {
clearInterval(timer);
console.log("done");
}, 3000);Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {
max-height: 100% !important;
}Run Code Online (Sandbox Code Playgroud)
你的第二个块不是立即使用setTimeout块,因为promise执行器函数(你传递的函数new Promise)立即和同步运行,而你没有做任何事情来使它异步.
你可以在这里看到; 柜台立即停顿,不迟于:
function slowFunction() {
return new Promise(resolve => {
const stop = Date.now() + 2000;
while (Date.now() < stop) {
// busy wait (obviously, never really do this)
}
});
};
console.log("before slowFunction");
slowFunction()
.then(() => {
console.log("then handler on slowFunction's promise");
})
.catch(console.error);
console.log("after slowFunction");
let counter = 0;
const timer = setInterval(() => {
console.log(++counter);
}, 100);
setTimeout(() => {
clearInterval(timer);
console.log("done");
}, 3000);Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {
max-height: 100% !important;
}Run Code Online (Sandbox Code Playgroud)
我们甚至没有看到之前的慢功能日志出现,直到长时间运行的代码完成,因为浏览器永远没有机会重新绘制,我们让线程陷入困境.
关于async功能:在该代码async功能开始时同步,并且是同步的,直到第一await(或其他构建体,如setTimeout,即时间表事后执行).只有那之后的代码是异步的(因为它必须等待).
这是一个证明:
async function foo() {
console.log("before await");
await Promise.resolve();
console.log("after await");
}
console.log("before foo");
foo()
.then(() => {
console.log("then handler on foo's promise");
})
.catch(console.error);
console.log("after foo");Run Code Online (Sandbox Code Playgroud)
这是输出:
before foo before await after foo after await then handler on foo's promise
注意在foo 之前await之前是如何发生的; 它与调用同步.但是之后等待直到稍后才会发生(因为必须让它后面的代码异步发生;它的语法糖,即使承诺已经解决,也承诺不会同步调用它的处理程序).fooawait Promise.resolve()then