对阻塞操作的执行感到困惑 JavaScript 即(执行顺序)
Confused about blocking operation's execution JavaScript i.e (execution order)
async () => {
try {
setTimeout(() => console.log('next task'), 0);
await timeTakingFunc();
console.log('after waiting for timetaking function');
} catch (error) {
console.log(error.message);
}})();
输出:
等待计时功能后
下一个任务
不应该'next task'首先打印为timeTakingFunction();执行时间很长,超时只有 0 毫秒?
计时功能:
async function timeTakingFunc() {
return new Promise((resolve, error) => {
for (let t = 1; t < 100000; t++) {
for (let k = 1; k < 100000; k++) {
}
}
resolve();
});
};
您的 timeTakingFunc
会同步完成所有工作,原因有二:
async
函数的代码在第一个 await
或 return
之前是同步的。这样它就可以启动要异步完成的任何进程。
- 您传递给
new Promise
的执行程序函数是 运行 同步的,运行 在新承诺返回到进行调用的代码之前完成 - 出于相同的原因 async
函数同步启动。 (实际上,async
函数的开头,在第一个 await
或 return
之前,直接类似于承诺执行函数的主体。)
所以这个函数实际上并没有什么异步的。
(旁注:没有理由在从不使用 await
并且显式创建其承诺的函数上使用 async
。这是多余的。)
如果函数中有任何实际的异步工作几乎需要任何时间才能完成,您将看到您期望的输出顺序:
async function timeTakingFunc() {
// This fetch fails, but it takes non-zero time to do so
try {
const response = await fetch("https://via.placeholder.com/150");
if (response.ok) {
await response.arrayBuffer();
}
} catch (e) {
}
}
(async () => {
try {
setTimeout(() => console.log('next task'), 0);
await timeTakingFunc();
console.log('after waiting for timetaking function');
} catch (error) {
console.log(error.message);
}
})();
但是使用该代码,timeTakingFunc
是同步的:
async function timeTakingFunc() {
const p = new Promise((resolve, error) => {
console.log("Start of executor function");
for (let t = 1; t < 100000; t++) {
for (let k = 1; k < 100000; k++) {}
}
console.log("End of executor function");
resolve();
});
console.log("timeTakingFunc returning promise");
return p;
};
(async () => {
try {
setTimeout(() => console.log('next task'), 0);
await timeTakingFunc();
console.log('after waiting for timetaking function');
} catch (error) {
console.log(error.message);
}
})();
...JavaScript 引擎执行此操作:
- 设置计时器(在某些时候会将任务排队到 运行 计时器回调)
- 运行
timeTakingFunction
的同步部分(全部)直至完成
- [因为
await
] 将当前任务的微任务队列中的微任务排队到 运行 代码的其余部分
- 到达当前任务的结尾
- 处理微任务队列
- 运行代码的剩余部分,记录
"after waiting for timetaking function"
- 处理任务队列中的下一个任务,可能是定时器回调(如果不是,它很快就会出现在队列中)
- 当定时任务为运行时,记录
"next task"
这就是为什么你看到的顺序是同步的。
async () => {
try {
setTimeout(() => console.log('next task'), 0);
await timeTakingFunc();
console.log('after waiting for timetaking function');
} catch (error) {
console.log(error.message);
}})();
输出:
等待计时功能后
下一个任务
不应该'next task'首先打印为timeTakingFunction();执行时间很长,超时只有 0 毫秒?
计时功能:
async function timeTakingFunc() {
return new Promise((resolve, error) => {
for (let t = 1; t < 100000; t++) {
for (let k = 1; k < 100000; k++) {
}
}
resolve();
});
};
您的 timeTakingFunc
会同步完成所有工作,原因有二:
async
函数的代码在第一个await
或return
之前是同步的。这样它就可以启动要异步完成的任何进程。- 您传递给
new Promise
的执行程序函数是 运行 同步的,运行 在新承诺返回到进行调用的代码之前完成 - 出于相同的原因async
函数同步启动。 (实际上,async
函数的开头,在第一个await
或return
之前,直接类似于承诺执行函数的主体。)
所以这个函数实际上并没有什么异步的。
(旁注:没有理由在从不使用 await
并且显式创建其承诺的函数上使用 async
。这是多余的。)
如果函数中有任何实际的异步工作几乎需要任何时间才能完成,您将看到您期望的输出顺序:
async function timeTakingFunc() {
// This fetch fails, but it takes non-zero time to do so
try {
const response = await fetch("https://via.placeholder.com/150");
if (response.ok) {
await response.arrayBuffer();
}
} catch (e) {
}
}
(async () => {
try {
setTimeout(() => console.log('next task'), 0);
await timeTakingFunc();
console.log('after waiting for timetaking function');
} catch (error) {
console.log(error.message);
}
})();
但是使用该代码,timeTakingFunc
是同步的:
async function timeTakingFunc() {
const p = new Promise((resolve, error) => {
console.log("Start of executor function");
for (let t = 1; t < 100000; t++) {
for (let k = 1; k < 100000; k++) {}
}
console.log("End of executor function");
resolve();
});
console.log("timeTakingFunc returning promise");
return p;
};
(async () => {
try {
setTimeout(() => console.log('next task'), 0);
await timeTakingFunc();
console.log('after waiting for timetaking function');
} catch (error) {
console.log(error.message);
}
})();
...JavaScript 引擎执行此操作:
- 设置计时器(在某些时候会将任务排队到 运行 计时器回调)
- 运行
timeTakingFunction
的同步部分(全部)直至完成 - [因为
await
] 将当前任务的微任务队列中的微任务排队到 运行 代码的其余部分 - 到达当前任务的结尾
- 处理微任务队列
- 运行代码的剩余部分,记录
"after waiting for timetaking function"
- 运行代码的剩余部分,记录
- 处理任务队列中的下一个任务,可能是定时器回调(如果不是,它很快就会出现在队列中)
- 当定时任务为运行时,记录
"next task"
- 当定时任务为运行时,记录
这就是为什么你看到的顺序是同步的。