Promise.resolve 是异步函数吗?

Posted

技术标签:

【中文标题】Promise.resolve 是异步函数吗?【英文标题】:Is Promise.resolve a asynchronous function? 【发布时间】:2018-07-21 19:53:35 【问题描述】:

当我有以下代码时:

var promise1 = Promise.resolve([1, 2, 3]);

promise1.then((value) => 
  console.log(value);
  // expected output: Array [1, 2, 3]
);


console.log('end of script');

我知道脚本的结尾会提前返回,因为 promise 是异步的。但是在什么执行点它会变成异步的呢?

Promise.resolve() 是异步的吗? 或者.then 是异步的,甚至是两个函数? 是否还有其他机制在发挥作用?

(对谷歌来说简直是地狱,因为我只得到新的async await 功能的结果)

【问题讨论】:

这可能会有所帮助:developer.mozilla.org/en-US/docs/Web/javascript/EventLoop 【参考方案1】:
 Promise.resolve([1, 2, 3]);

Promise.resolve() 是异步的吗?

不,这只是一个常规的函数调用。它会立即返回一个结果。

或者是.then异步的,甚至是两个函数

没有。从某种意义上说,两者都不是异步的

promise1.then((value) => console.log(value));

立即返回一个用于链接的新 Promise。

然而,一个 Promise 肯定 resolves 异步,这意味着在你的整个同步代码执行之后,肯定会调用内部函数 (value => console.log(value))。

是否还有其他机制在发挥作用?

是的,后台有一个“魔法”事件循环,它管理所有异步事件。

【讨论】:

解析和调用回调是两件不同的事情。我认为在Promise.resolve([1, 2, 3]) 中,承诺是同步实现的(已解决)。即使在 Promise 执行器中调用 resolve 函数也是同步的,它会立即更改 Promise 状态。 @bergi with resolves 我指的是 then 回调被调用而不是 resolve() ...但是我承认我的声明允许解释...跨度> 是的,resolve 通常表示“将 promise 的状态设置为 resolved”。【参考方案2】:

但是在什么时候它会变成异步的呢?

当某些事情发生“不正常”时。

Promise.resolve() 是异步的吗?

通常不会。但是,是的,根据你用它调用它的参数,有时确实会安排一个 thenable 的同化以供以后使用。在你的情况下,传递一个数组,没有什么异步发生。

无论如何,它总是立即返回一个承诺。

或者.then是异步的,甚至是两个函数?

是的。 then 确实总是安排您稍后传入的回调函数。

当然,它也总是立即返回一个承诺。

一般来说,我们可以说观察一个 promise 结果总是异步的。

当询问一个函数是否异步时,不幸的是,我们的意思是该函数是异步调用(稍后),还是导致另一个函数被异步调用(通过调度异步事件)。

【讨论】:

【参考方案3】:

这是发生的确切顺序。在开始之前,您应该注意 Promise 对象始终处于以下三种状态之一:

    等待评估完成。 用最终值解决。 以“原因”值拒绝。

首先,promise1 被分配了一个处于“已解决”状态且最终值为 [1,2,3] 的承诺:

var promise1 = Promise.resolve([1, 2, 3]);

接下来,我们要求,一旦promise1 进入其已解决状态,我们记录其最终值。 但是,promise 中的 .then()、.catch() 等在整个程序通过并且执行进入 Javascript 事件循环之前永远不会被评估。因此,这段代码 注册将要完成但实际上并未完成的未来动作;这段代码会立即返回而不会完成。

promise1.then((value) => 
  console.log(value);
  // expected output: Array [1, 2, 3]
);

之后,我们打印一些文本:

console.log('end of script');

此时,Javascript的执行返回到它的事件循环,它找到了我们之前注册的.then(),并执行了相关函数((value) => console.log(value))。

这里有一篇有用的文章描述了事件循环如何与 Promise 一起工作:https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5

【讨论】:

谢谢!这让我对这个问题的答案有了详细的了解。【参考方案4】:

所有答案都很好,但我想在这里提一点微妙之处。在 JS 中,并非所有异步动物都是平等的。 Promise 使用微任务队列,而老式异步回调使用事件队列。

所以对于下面的代码,请在运行之前尝试猜测日志的顺序..

console.log("Code starts here");
setTimeout(console.log,0,"setTimeout resolved");
Promise.resolve("promise resolved")
       .then(s => (console.log(s), "yet another promise resolved"))
       .then(s => console.log(s));
console.log("Code ends here")

因此,正如您所见,Promises 使用的微任务队列对事件队列具有特权,并且当时间到来时,微任务队列头部的指令优先于事件队列头部的可怜指令,即使就像上面一样,它们同时解析。

【讨论】:

我认为您的代码不会演示这个“微任务队列”(如果存在)。 setTimeout(0) 在大约 4 毫秒后触发,因此无论有多个队列,该事件都会最后触发。

以上是关于Promise.resolve 是异步函数吗?的主要内容,如果未能解决你的问题,请参考以下文章

return Promise.resolve

js异步之async/await

Promise 简介

Promise原理讲解 async+await应用(异步回调解决方案)

如果一个promise永不resolve,会内存泄漏吗

JavaScript Promise异步实现章节的下载显示