将已解决的承诺值传递到最终的“then”链的最佳方法是啥[重复]

Posted

技术标签:

【中文标题】将已解决的承诺值传递到最终的“then”链的最佳方法是啥[重复]【英文标题】:What is the best way to pass resolved promise values down to a final "then" chain [duplicate]将已解决的承诺值传递到最终的“then”链的最佳方法是什么[重复] 【发布时间】:2013-09-21 20:38:19 【问题描述】:

我正在尝试使用 node.js 中的 Q 模块来理解 Promise,但是我有一个小问题。

在这个例子中:

ModelA.create(/* params */)
.then(function(modelA)
    return ModelB.create(/* params */);
)
.then(function(modelB)
    return ModelC.create(/* params */);
)
.then(function(modelC)

    // need to do stuff with modelA, modelB and modelC

)
.fail(/*do failure stuff*/);

.create 方法然后在每个 .then() 中返回一个 promise,正如预期的那样,得到 promise 的解析值。

但是在最后的 .then() 中,我需要拥有所有 3 个先前已解决的承诺值。

最好的方法是什么?

【问题讨论】:

How do I access previous promise results in a .then() chain? 的完全相同的副本 【参考方案1】:

这些是您众多选择中的一部分:

在门1之后,使用reduce将结果串联起来。

var models = [];
[
    function () 
        return ModelA.create(/*...*/);
    ,
    function () 
        return ModelB.create(/*...*/);
    ,
    function () 
        return ModelC.create(/*...*/);
    
].reduce(function (ready, makeModel) 
    return ready.then(function () 
        return makeModel().then(function (model) 
            models.push(model);
        );
    );
, Q())
.catch(function (error) 
    // handle errors
);

在2号门后,将积累的模型打包成一个数组,用spread解包。

Q.try(function () 
    return ModelA.create(/* params */)
)
.then(function(modelA)
    return [modelA, ModelB.create(/* params */)];
)
.spread(function(modelA, modelB)
    return [modelA, modelB, ModelC.create(/* params */)];
)
.spread(function(modelA, modelB, modelC)
    // need to do stuff with modelA, modelB and modelC
)
.catch(/*do failure stuff*/);

在门 3 之后,在父作用域中捕获结果:

var models [];
ModelA.create(/* params */)
.then(function(modelA)
    models.push(modelA);
    return ModelB.create(/* params */);
)
.then(function(modelB)
    models.push(modelB);
    return ModelC.create(/* params */);
)
.then(function(modelC)
    models.push(modelC);

    // need to do stuff with models

)
.catch(function (error) 
    // handle error
);

【讨论】:

在我发布这个问题之前,我已经完成了与“3 号门”完全一样的操作:) 但是我对这种方法不太满意,想知道其他方法。所以我会选择 2 号门,因为它不需要“外部”变量的“帮助”。顺便说一句,我不得不说 Kris,在那里与 Q 的工作很棒,回调可能会永远消失 :) 我喜欢 1 号门,因为它很聪明,但乍一看完全不可读。摸索它需要一些脑力,而 2 号门是立即可读的。感谢您的回答:)【参考方案2】:

Bluebird promises 库通过.bind() 提供了另一种解决方案。

看起来像这样:

ModelA.create(/* params */).bind()
.then(function (modelA) 
    this.modelA = modelA;
    return ModelB.create(/* params */);
)
.then(function (modelB) 
    this.modelB = modelB;
    return ModelC.create(/* params */);
)
.then(function (modelC) 
    // you have access to this.modelA, this.modelB and modelC;
);

documentation 中有很多关于这个方法的有趣信息。

【讨论】:

非常非常的赢【参考方案3】:

您可能不需要等到创建模型A 再创建模型B 等等。 如果这是真的,那么您可以执行以下操作:

var promises = [
  ModelA.create(...),
  ModelB.create(...),
  ModelC.create(...)
);

Q.all( promises ).spread(function( modelA, modelB, modelC ) 
  // Do things with them!
).fail(function() 
  // Oh noes :(
);

这是做什么的:

创建一组 Promise,为您需要的每个模型创建一个 Promise; 并行执行所有 3 个承诺; 当所有 3 个 promise 都完成后,执行传入 spread() 的函数。参数是每个 Promise 的解析值,按照声明顺序。

希望对你有帮助:)

【讨论】:

谢谢,这在我的特殊情况下有效,但是我仍然想知道一种方法来让这些承诺按顺序执行,并且每个承诺都等待前一个实现并最终得到所有的结果。 一种方法是在可访问范围内设置变量(例如,ModelA.create() 被调用的范围)。

以上是关于将已解决的承诺值传递到最终的“then”链的最佳方法是啥[重复]的主要内容,如果未能解决你的问题,请参考以下文章

从承诺返回 then()

承诺,如何将变量传递给 .then 函数

承诺执行条件

承诺后的返回值[重复]

RSVP Promises:then() 链返回链的第一个值

承诺问题 - .then() 没有被调用?