【问题标题】:DRY up promises in javascript在 javascript 中干掉 Promise
【发布时间】:2016-07-29 01:49:35
【问题描述】:

我在节点 v6.3.0 中有以下代码在运行两个单独的 Promise 的 api 上运行,具体取决于 POST 请求中是否存在参数。

if (paramExists) {
    // call database with this query
    User.filter(/* do something with param */)
        .then(function (user) {
            Data.filter(/* same in both conditions */)
                .then(function (data) {
                    // join data and user
                    res.send(joinedData);
                })  // omit catch for clarity
        })  // omit catch for clarity
} else {
    // call database with this query
    User.filter(/* do something with header */)
        .then(function (user) {
            Data.filter(/* same in both conditions */)
                .then(function (data) {
                    // join data and user
                    res.send(joinedData);
                })  // omit catch for clarity
        })  // omit catch for clarity
}

我确信有办法干掉这段代码,以便在两种情况下的第一个承诺都将用户传递给第二个承诺,但我不知道如何。我应该使用生成器,还是有办法通过我没有得到的承诺来做到这一点?

【问题讨论】:

  • 你考虑过Promise.all。它最终看起来像var p1 = User.filter(paramExists ? args1 : args2), p2 = Data.filter(...); Promise.all([p1, p2]).then(function (user, data) { ... });
  • 听起来你在问conditions in promise chains

标签: javascript node.js promise generator


【解决方案1】:

由于两个分支之间似乎唯一不同的部分是您传递给User.filter() 的内容,因此您可以将该值放入条件中的局部变量中,然后使用该变量运行一个版本的代码。

你也可以简化你的链式方法来移除不必要的嵌套:

var arg; 
if (paramExists) {
    arg = ...     // some logic
} else {
    arg = ...     // some different logic
}
// call database with this query
User.filter(arg).then(function (user) {
    return Data.filter(...);
}).then(function (data) {
    // join data and user
    res.send(joinedData);
});  // omit catch for clarity

你也可以使用三元:

var arg = paramExists ? someLogic : someOtherLogic;
// call database with this query
User.filter(arg).then(function (user) {
    return Data.filter(...);
}).then(function (data) {
    // join data and user
    res.send(joinedData);
});  // omit catch for clarity

如果您需要同时访问 userdata 来发送响应(在您的伪代码中有点难以分辨),那么您可以保留嵌套:

var arg = paramExists ? someLogic : someOtherLogic;
// call database with this query
User.filter(arg).then(function (user) {
    return Data.filter(...).then(function(data) {
        // join data and user
        res.send(joinedData);
    });
});  // omit catch for clarity

【讨论】:

  • 我认为这可能是一个问题,因为 OP 需要将第一个承诺的结果与第二个承诺相结合,并且使用您的链式回调方法,返回的用户数据超出范围。
  • @numbers1311407 - 我重新添加了该选项。有时在伪代码中很难说出那种详细程度。或者,他们还可以与these schemes 之一共享同一级别的数据。
  • 实际上是的,第二个选项有效。谢谢你,学会爱承诺。
【解决方案2】:

您可以执行以下操作。我假设Data.filter 也会返回一个承诺。

if (paramExists) {
    // call database with this query
    User.filter(/* do something with param */)
        .then(sameCondition);  // omit catch for clarity
} else {
    // call database with this query
    User.filter(/* do something with header */)
        .then(sameCondition);  // omit catch for clarity
}

function sameCondition(user) {
  return Data.filter(/* same in both conditions */)
    .then(function (data) {
      // join data and user
      res.send(joinedData);
  });  // omit catch for clarity
}

【讨论】:

  • 您可以更简单,只需根据条件将不同的参数传递给第一个承诺,例如User.filter(paramExists ? args1 : args2).then(restOfBehavior);
  • 看起来很简单,我试试看。
【解决方案3】:

做这样的事情...

var task1 = paramExists ? 
   User.filter(/* do something with param */) :
   User.filter(/* do something with header */)

var doFilter = task1.then(function () {
   return Data.filter(/* same in both conditions */)
})

doFilter.then(function (joinedData) {
   res.send(joinedData);
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    相关资源
    最近更新 更多