【问题标题】:Sequelize Promises - Chaining Promises and Bluebird Promise.each, Promise.map, Promise.all etcSequelize Promises - 链式 Promise 和 Bluebird Promise.each、Promise.map、Promise.all 等
【发布时间】:2020-05-10 00:35:40
【问题描述】:

我的用户控制器中有一个索引操作,其中我试图连续做两件事,并且在他们都有机会完成之前不执行所需的 res.json() 方法。

我有一个加入用户的友谊加入模型。一列是frienderId,一列是friendedId。在下面的索引函数中,期望的结果是我将得到一个 SINGLE 用户对象,它是一个朋友。下面有承诺的原因是因为用户可能在frienderId 列或friendedId 列中,所以我必须从本质上解析req.user 的朋友的两种可能情况。

问题是最后返回的东西,即 I.E. res.json(result),总是返回正确的朋友,但是,它总是在所需对象之前或之后返回一个空数组 []。我知道这个空数组来自两个未找到结果的承诺场景之一。是否有某种类型的方法而不是像sayyy..reject 这样的解决方法?其中如果调用,整个promise不会被推送到promise数组中?然后我可以测试 if (!friended) {reject} 或 if (!friender) {reject}

我了解 .each 是在枚举每个承诺并给出每个承诺的结果。但是,我不想要每个 Promise 的结果,我只想访问每个 Promise 运行的副作用。

谢谢!

index: function(req, res) {
    var promiseArray = [];

    promiseArray.push(new Promise(function(resolve) {
      user.findById(req.user.id).then(function(user) {
        user.getFrienders({
          where: {
            username: req.body.username
          }
        }).then(function(friender) {
          resolve(friender[0])
        })
      })
    }));

    promiseArray.push(new Promise(function(resolve) {
      user.findById(req.user.id).then(function(user) {
        user.getFriendeds({
          where: {
            username: req.body.username
          }
        }).then(function(friended) {
          resolve(friended[0])
        })
      })
    }));

    Sequelize.Promise.map(promiseArray, function(result) {
      res.json(result);
    });
}

【问题讨论】:

  • 另一个奇怪的事情是,当我不是简单地在最底部的 res.json(result) 下,在最顶部的 var promiseArray 下添加一个未定义的变量,称为 var friend,然后是 console.log (friend) 在最后的 Sequelize.Promise.map 函数中,结果是两个值。第一个是未定义的,然后第二个是正确的朋友对象,反之亦然,具体取决于用户所在的列 (frienderId或friendedId)。对于在世界控制台中记录单个变量如何导致记录两个完全不同的值,一个接一个地,非常困惑。谢谢。

标签: sql node.js promise sequelize.js bluebird


【解决方案1】:

首先,您对Promise 的使用有点多余。因为findById() 函数返回一个promise,所以你需要做的就是处理它。您无需创建new Promise。你可以说promiseArray.push(user.findById ...)。您几乎可以正确使用then。传递给then 的函数将在promise 被解析时被调用,在这种情况下,在findById 函数完成并返回一个值之后。 then 本身返回一个用回调返回的值解析的承诺。因此,当一切完成后,无论您希望在 promiseArray 中得到什么值,我假设 friended[0]friender[0] 您只需要在最后一个 then 函数中返回该值。在第一个then函数里面,你也应该说return user.findFriends( ...

接下来你需要做的是处理findById函数返回的promise被拒绝的情况。你可以通过两种方式做到这一点。首先,您可以将第二个回调传递给then,在promise 被拒绝的情况下将调用该回调,并以reject 的原因作为其参数。除了将两个函数传递给then,您可以跟随thencatch,这是我个人更喜欢做的事情,并将您的拒绝回调传递给catchcatch 还返回一个用回调返回的值解析的承诺。您可以选择返回传入的原因,或者您想要的任何值。因此,在错误被拒绝的情况下,无论catch 返回什么,最终都会出现在您的 promises 数组中。

阅读the documentation 的承诺可能对您有所帮助。诚然,我知道我刚开始使用 Promise 时遇到了一些困难,但是在阅读了文档并编写了示例之后,您就会掌握它并了解 Promise 的用处。

如果是我,我会这样重构代码

    var frienderPromise = user.findById(req.user.id)
          .then(function(user) {
            return user.getFrienders({
              where: { username: req.body.username }
            });
          })
          .then(function (friender) {
            return friender[0];
          })
          .catch(function (reason) {
            return reason; // or whatever else you want to end up in the promisesArray on rejection
          });

    var friendedPromise = user.findById(req.user.id)
          .then(function(user) {
            return user.getFriendeds({
              where: { username: req.body.username }
            });
          })
          .then(function (friended) {
            return friended[0];
          })
          .catch(function (reason) {
            return reason;
          });

    promiseArray.push(frienderPromise);
    promiseArray.push(friendedPromise);

您可以保持其他一切不变。最后,您仍然可以像现在一样拨打Sequalize。虽然它应该是return Sequalize...。如果您不想保留不好的结果,您也可以考虑使用Promise.filter 而不是.map。所以你可以做类似的事情

    return Sequelize.Promise.filter(promiseArray, function(result) {
      if (/* make sure it's result you want */)
        res.json(result);
    });

就个人而言,我会更进一步,将所有承诺业务删除到另一个与 res 无关的函数中,然后用

完成它
    return Sequelize.Promise.filter(promiseArray, function(result) {
      return result === /* result you want */;
    });

然后一旦进入你的index 函数,你就可以调用

    return friendsPromiseFunction().then(function (results) {
      res.json(results);
    })

这会让事情变得更干净。

【讨论】:

  • 我最终没有使用 Bluebird Promise 方法,而是使用常规的 sequelize Promise 链。这个过程对我来说是一个实验,我没有意识到我可以对 FRIENDED 进行查询,然后只需使用 .then 调用并对 FRIENDER 执行相同的查询,然后我就可以开始了。然后我能够访问 FRIENDED 和 FRIENDER 作为返回值,几个查询沿着承诺链进行,没有任何问题。谢谢您的帮助!赞成。
猜你喜欢
  • 2017-08-11
  • 2023-03-12
  • 1970-01-01
  • 2017-04-09
  • 2015-02-08
  • 1970-01-01
  • 1970-01-01
  • 2014-11-07
  • 1970-01-01
相关资源
最近更新 更多