【问题标题】:Passing an extra parameter in the middle of a Promise chain在 Promise 链的中间传递一个额外的参数
【发布时间】:2016-02-17 09:45:51
【问题描述】:

我需要在 Promise 链的中间添加一个 userID 参数(这是唯一需要它的 Promise)。所有的承诺都应该以同步的顺序执行。

SideNote-stackoverflow 上的所有类似示例都有些不同-例如使用 lambda 函数(我使用声明的函数)。所以我仍然不太确定。

var initialize = function(userID) {
      var firstPromise = Module2.getFirstPromise();
          firstPromise.then(getSecondPromise)
         .then(getThirdPromise)                     
         .then(getFourthPromise)  //<----Fourth promise needs userID
         .then(getFifthPromise)
         .then(Utils.initializeComplete);
  }

所有的 Promise 都是如下所示的函数:

var thirdPromise = function() {
   return new Promise(function(resolve, reject) {
      //fetch data
        //On Return, Store it
         resolve() //Nothing needed to passed down from this promise
      });

    });

}

我正在尝试这个,它“有效”,但我不确定这是否是我“假设”处理此类事情的方式。 :)

var initialize = function(userID) {
      var firstPromise = Module2.getFirstPromise();
          firstPromise.then(getSecondPromise)
         .then(getThirdPromise)                     
         .then(function(){ return fourthPromise(userID)})
         .then(getFourthPromise)
         .then(Utils.initializeComplete);
  }

注意:getFirstPromise 来自我代码中的不同模块。不过,这对这个问题应该不重要:)

【问题讨论】:

  • 你的问题有点不清楚。您是否收到错误或意外结果?
  • 这真的很令人困惑,你有firstPromise,它显然是指一个承诺,然后是secondPromise等等,它似乎是指函数。我建议更改该命名。
  • 除了其他 cmets 之外,您传递具有访问 userID 范围的内联函数的方法很好,并且是公认的模式。
  • @T.J.Crowder 我在第二个 sn-p 中描述了所有其他函数的样子。不知道如何才能更清楚,但我愿意提出建议。
  • @NickPineda:你不认为firstPromise 是一个承诺而secondPromise 是一个函数 令人困惑吗?!至于建议,看我的回答。

标签: javascript promise ecmascript-6 es6-promise


【解决方案1】:

假设firstPromise 确实是一个promise,但secondPromise 等等实际上是函数returning promise,那么是的,你所做的就是你应该如何做。 Here's a live example on Babel's REPL,看起来像这样:

function doSomething(userID) {
  getFirstPromise()
    .then(getSecondPromise)
    .then(getThirdPromise)
    .then(() => getFourthPromise(userID))
    // Or .then(function() { return getFourthPromise(userID); })
    .then(getFifthPromise)
    .catch(err => {
      console.log("Error: " + err.message);
    });
}
doSomething("foo");
function getFirstPromise() {
  console.log("getFirstPromise called");
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("one");
    }, 0);
  });
}
// and then second, third, fourth (with user ID), and fifth

(如果您不使用箭头函数,只需将它们替换为 function 表单即可。)


请注意上面示例中的catch。除非您有非常好的理由不这样做,否则如果您没有return 结果,则承诺链应该始终具有.catch

【讨论】:

    【解决方案2】:

    您的解决方案非常好。使用具体的签名可能更容易理解。

    如果您的thirdPromise 不接受任何内容并且不返回任何内容,则其签名可能会被写入(假设a -&gt; b 是从a 到b 的函数的伪代码)为_ -&gt; Promise (_)。如果它返回某个值a,它将是_ -&gt; Promise (a)。如果它取了一些东西并返回了一些东西,它可能是a -&gt; Promise (b)

    因此,您可以将您的 Promise 链推断为函数获取一些值并返回包装在 Promise 中的一些其他值。但是,您的 fourthPromise 看起来不同:

    fourthPromise : UserId -> a -> Promise (b)
    

    可以写成:

    fourthPromise : UserId -> (a -> Promise (b))
    

    它需要一个参数成为你可以链接的实际承诺。在某种程度上,它是一个承诺的模板。

    【讨论】:

      【解决方案3】:

      如果你想在 main 函数中使用普通的 .then 链,请尝试将 getFourthPromise 编写为工厂函数

      function getSomethingByUserID(userId) {
         return function() {
              return new Promise(function(resolve) {
                  //your actual async job
                  resolve('a result');
              });
         };
      }
      

      然后你会得到thens的计划列表

       var firstPromise = Module2.getFirstPromise()
           .then(getSecondPromise)                   
           .then(getSomethingByUserID(userId))
           .then(Utils.initializeComplete);
      

      不要忘记,如果您错过将userId 提供给getSomethingByUserID,它将无法正常工作。

      【讨论】:

        猜你喜欢
        • 2016-05-17
        • 1970-01-01
        • 2016-05-09
        • 1970-01-01
        • 2014-10-04
        • 2019-01-28
        • 2014-03-25
        • 2019-09-04
        • 1970-01-01
        相关资源
        最近更新 更多