【发布时间】:2020-02-12 08:10:25
【问题描述】:
我是 JS 新手,正在学习 promise。所以,假设我们有这样的代码:
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)
alert(result); // 1
return result * 2;
})
如您在上面的代码中看到的,当调用 promise 时,setTimeout 通过回调队列运行。问题是当 setTimeOut 被发送到浏览器时,JS 引擎是否会省略 .then() 并继续运行其余代码,直到 promise 解决?其次,async/await 示例:
async function showAvatar() {
// read our JSON
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
// read github user
let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
let githubUser = await githubResponse.json();
// show the avatar
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// wait 3 seconds
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
return githubUser;
}
showAvatar();
调用showAvatar函数时,JS引擎会遇到let response = await fetch('/article/promise-chaining/user.json');,发送fetch到浏览器处理。第二个问题是 JS 引擎会等到 fetch 解决还是 JS 引擎会继续执行 let user = await response.json(); 以及 showAvatar 函数中的其余代码?如果是这样,由于没有收到响应,JS引擎如何处理 response.json() ?希望你明白我的意思)))。
【问题讨论】:
-
在您的第一个示例中,承诺在计时器结束时被解决,因此浏览器等待计时器的持续时间,这解决了承诺,然后它才能执行
.then()中的回调。在您的第二个问题中,正如名称await所暗示的那样,它将暂停代码的执行,直到正在等待的承诺得到解决。由于浏览器在等待user.json响应,所以在收到响应之前不会执行下一行。 -
@Terry,嗨,感谢您的好心 cmets,在第一个示例中,如果 JS 引擎等到 promise 解决后再运行 then(),我认为它会阻止交互。关于第二个例子,如果 await 使函数停止,那么通过使用 async 我们将 showAvatar 函数推到调用堆栈之外,这样它就不会阻塞主堆栈,这是真的吗?
-
@MII - 它们都不会阻塞等待承诺解决的主要 JavaScript 线程。一旦引擎连接了
then处理程序,它就会继续做其他事情,直到计时器触发。async函数在每个await处暂停,允许线程做其他事情,并在等待的承诺解决时恢复。 -
@T.J.Crowder,关于 async/await 示例,当 async 函数在每个 await 处挂起时,async 函数是否会从调用堆栈中移除,并在等待 promise 时再次放回调用堆栈解决了吗?
-
@MII - 我在下面的答案中添加了一个答案。
标签: javascript