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 是异步函数吗?的主要内容,如果未能解决你的问题,请参考以下文章