假设我有这个模块:
export async function beFancy () {
let i, j, load;
// just for trying to delay the return;
for (i = 0; i < 999; ++i) {
for (j = 0; j < 999; ++j) {
load = i + j;
}
}
return 'beFancy finished';
}
现在我制作了一个主要模块进行测试:
import {beFancy} from './mymodule';
beFancy().then((msg) => console.log(msg));
console.log('main finished');
如果我执行,输出是预期的
-> main finished
-> beFancy finished
因为beFancy
是-asynchronous -
但是现在如果我试图使循环更加激烈:
export async function beFancy() {
let i, j, load;
for (i = 0; i < 9999999; ++i) {
for (j = 0; j < 999; ++j) {
load = i + j;
}
}
return 'beFancy finished';
}
再次执行main
,输出相同
-> main finished
-> beFancy finished
但我希望在实际处理函数main finished
之前显示beFancy
。相反,当beFancy
完成时,上面的输出会一次显示。起初我认为原因是因为输出只在程序结束时刷新,但如果我输入:
console.log('begin');
beFancy().then((msg) => console.log(msg));
console.log('main finished');
因为beFancy
是 - 同步 - 可能是错的?这是我机器上的意外行为吗?
答案 0 :(得分:1)
因为beFancy是 - 同步 - 可能是什么错误?
那是因为它只有beFancy
返回的异步值。 beFancy
主要是同步并阻塞主线程。上面的代码大致相同:
function beFancy () {
return new Promise(resolve => {
let i, j, load;
for (i = 0; i < 999; ++i) {
for (j = 0; j < 999; ++j) {
load = i + j;
}
}
console.log('logged on same tick')
resolve('logged on next tick');
});
}
console.log('begin');
beFancy().then((msg) => console.log(msg));
console.log('main finished');
为了使async
函数中的循环具有异步和非阻塞性,它应该使用await
的块执行:
export async function beFancy () {
let i, j, load;
for (i = 0; i < 999; ++i) {
await null; // next tick
for (j = 0; j < 999; ++j) {
load = i + j;
}
}
return 'beFancy finished';
}
答案 1 :(得分:0)
JavaScript在单个线程上运行。通过利用异步非阻塞I / O,它可以实现多线程语言的性能平衡(有时甚至是优势)。
这很有效,因为大多数情况下,在多线程语言中,应用程序线程处于空闲状态,等待异步I / O请求返回。在JavaScript中,等待请求被停放,线程继续在其他地方执行。
当您在网络电话或磁盘上等待时,这很棒,但如果您的异步请求正在咀嚼CPU,那么线程就会随之而来。因此,上面为所有意图和目的使用的代码执行同步。
这里是代码的执行顺序:
使用setTimeout( () => console.log('done!'), 1500)
替换CPU密集型for循环,您应该会看到预期的结果。