Q Promise 啥时候执行?
Posted
技术标签:
【中文标题】Q Promise 啥时候执行?【英文标题】:When do Q promises get executed?Q Promise 什么时候执行? 【发布时间】:2017-02-20 13:57:42 【问题描述】:我在理解 Promise 时遇到了一个(看似根本的)问题。先上代码:
'use strict';
var Q = require("q");
var mockPromise = function (statement)
var deferred = Q.defer();
console.log("I'm running before I'm queued ...");
setTimeout(function ()
deferred.resolve(statement);
, 5000);
return deferred.promise;
;
var promises = [
mockPromise("1st statement"),
mockPromise("2nd statement"),
mockPromise("3rd statement")
];
Q.all(promises)
.then(function (results)
console.log(results);
);
每个 promise 函数都会在将其添加到 promise 数组时被调用,而不是像我想象的那样调用 Q.all。
我在这里没有得到什么?
如何在不立即调用承诺的情况下将一组承诺排队?
【问题讨论】:
为什么要将promise排队然后执行呢?如果它们一被触发就执行,速度会更快Q.all()
只是一个承诺,只有在其数组中的所有承诺完成后才会完成
看到这些***.com/questions/35543964/…***.com/questions/38694958/…
promise 是一个结果值,没有任何东西可以执行或调用。你想要的是一个返回承诺的函数——你可以随时存储和调用。
【参考方案1】:
Promise 是对象。它们没有被“执行”。他们被“解决”或“拒绝”。创建数组时,您正在执行 mockPromise() 函数 3 次。这个函数会立即在代码的那个点执行。
mockPromise() 函数创建一个 deferred 并返回相关的 Promise。它还设置了一个计时器来解决将来返回的承诺。
Q.all() 只是等待 3 个承诺被“解决”。 (从技术上讲,它返回一个新的 Promise,当之前的 3 个 Promise 被解决时,该 Promise 将被解决)
如果你想一个接一个地执行三个异步函数,我会推荐使用优秀的async.js 库。它提供了许多异步流控制原语。在您的情况下,您可能对 series 或 waterfall 方法感兴趣。
【讨论】:
我真的很喜欢你的回复@tato。在我的(未简化的)案例中,返回承诺的函数会根据计算添加到数组中。我注意到,甚至在数组完全填充之前,函数就被调用了。这不是一个大问题,但这不会造成竞争条件吗? ...也就是说,如果 promises 数组仍在填充,Q.all(promises) 不能过早读取完成吗? 在 javascript 中你永远不会有竞争条件。它是单线程的。所以第一次调用 mockPromise() 将在开始第二次之前完全执行。但是,请注意,mockPromise() 的完整执行 只涉及启动计时器。计时器完成将在未来发生,并将解决承诺。 ... 和 Q.all() 直到对 mockPromise() 的三个调用完全执行后才会执行(同样,只启动计时器) @Lindauson 不,Q.all(promises) 永远不会过早读取完成,从 Q.all(promises) 返回的承诺将不会被解决,直到数组中的所有承诺都完成(解决或拒绝) )【参考方案2】:似乎令人困惑的是,您理解 Promise API 是为惰性评估而设计的,但事实并非如此。
Promise 是一种处理长时间运行请求的方式,它们旨在立即启动以最大限度地减少等待时间,并利用链接和连接来阐明应如何处理这些长时间运行请求的结果。
您可以尝试使用 api Q-Lazy,它允许您延迟调用 Promise,直到它们被订阅。
【讨论】:
似乎 Q API 更关心同步承诺完成与同步调用。您认为这是一个正确的评估吗? @Lindauson Promises 与调用无关 @Lindauson 没有真正同步,因为 Promise api 对时间的影响很小,但组织会很准确,Q API 有助于根据成功和失败条件组织回调的执行链。 【参考方案3】:您通常会延迟异步功能,而不仅仅是一个值。例如:
'use strict';
var Q = require("q");
var mockPromise = function (statement)
var deferred = Q.defer();
console.log("I'm running before I'm queued ...");
setTimeout(function ()
deferred.resolve(statement());
, 5000);
return deferred.promise;
;
var promises = [
mockPromise(function()
console.log("running1");
return "1st statement";
),
mockPromise(function()
console.log("running2");
return "2nd statement";
),
mockPromise(function()
console.log("running3");
return "3rd statement";
),
];
Q.all(promises)
.then(function (results)
console.log(results);
);
请注意,延迟功能将运行,无论您是否曾在承诺上调用.then
。
【讨论】:
感谢您的回复安德鲁。对我来说更有趣的是,即使没有/之前调用 Q.all(promise),函数也会被执行。【参考方案4】:让我展示一个使用标准承诺的示例。它们的工作方式与 Q 承诺几乎相同:
function mockPromise(value)
return new Promise(resolve =>
console.log("I'm not running before I'm queued ...");
setTimeout(() =>
resolve(value);
, 1000);
);
mockPromise("1st promise").then(x =>
console.log(x);
return mockPromise("2nd promise");
).then(x =>
console.log(x);
return mockPromise("3nd promise");
).then(x =>
console.log(x);
);
【讨论】:
以上是关于Q Promise 啥时候执行?的主要内容,如果未能解决你的问题,请参考以下文章