【问题标题】:Manipulate object and array returned by Promise操作 Promise 返回的对象和数组
【发布时间】:2019-01-07 11:48:04
【问题描述】:

router.get('/', function (req, res, next) {
   var size = req.params.size ? parseInt(req.params.size) : 20;
   var page = req.params.page ? req.params.page>0 ? (size&(parseInt(req.params.page)-1)) : 0 : 0;

   db.knex.select('t.id', 't.title', 't.slug', 't.start_date', 't.end_date', 't.enable_date', 't.disable_date', 't.featured', 't.category', 't.status')
   .from('tournament AS t')
   .limit(size).offset(page)
   .then(result => {
          let arr = [];
          arr = result.map(x => {
               db.knex.select('td.id', 'td.d_title')
               .from('tournament_detail as td')
               .where('td.tournament_id', x.id)
               .asCallback((err, row) => {
                    if(err) return console.error(err);
                    x['detail'] = row;
                    console.log(x);
                    return x;
                });
          })
     }).catch(err => {
          console.log(err);
         res.send(err)
     })
 });

此代码生成图像中显示的结果,但我希望将这些对象合并到一个数组中。

如何实现?

请帮忙。

我的预期输出是这样的

【问题讨论】:

  • 对象已经合并到一个数组中,即你第一次调用的result数组。
  • 这是真的,但我想通过进行辅助 sql 调用来添加一个键值并将该返回值推送到第一次调用。
  • 请发布您的预期输出结果
  • 我已经更新了我的帖子检查预期的输出。

标签: javascript arrays express object promise


【解决方案1】:

我认为您遇到的问题是您使用的是result.map,它不会等待承诺解决,然后您使用的是基于承诺的 knex 查询。相反,您需要使用一个等待 Promise 执行的映射函数。如果您使用的是节点 8 或更高版本,您应该可以使用本机 Promise.all,如果您使用的是较低版本,我建议您尝试使用 Bluebird library。这会将您的代码更改为如下所示。

var Bluebird = require('bluebird');

router.get('/', function (req, res, next) {
   var size = req.params.size ? parseInt(req.params.size) : 20;
   var page = req.params.page ? req.params.page>0 ? (size&(parseInt(req.params.page)-1)) : 0 : 0;

   db.knex.select('t.id', 't.title', 't.slug', 't.start_date', 't.end_date', 't.enable_date', 't.disable_date', 't.featured', 't.category', 't.status')
   .from('tournament AS t')
   .limit(size).offset(page)
   .then(result => {
          return Bluebird.map(result, x => {
               return db.knex.select('td.id', 'td.d_title')
               .from('tournament_detail as td')
               .where('td.tournament_id', x.id);
          });
     }).then((arr) => {
         console.log(arr);
     })
     .catch(err => {
         console.log(err);
         res.send(err)
     })
 });

在上面,我们使用 Bluebird.map 循环遍历执行 knex 承诺的结果以检索第二个数据集。最后,arr 值将是地图查询结果的集合。

使用原生的Promise.all 类似,只需将Bluebird.map 替换为Promise.all 即可。

顺便说一句,如果您使用的是 nodejs 8 或更高版本,您还可以使用 async/await 使这段代码更好。这样,您就可以保留您的 results.map 并使用异步函数。

警告,我没有运行这段代码,所以它可能有一些语法错误等。但是使用 Bluebird.map 是您想要做的。

【讨论】:

  • 为什么不直接使用Promise.all() 而不是添加额外的库?
  • @RobbyCornelissen 我假设使用“var”这是节点的旧版本,但是我意识到现在有箭头函数,所以 Promise.all 会很好。顺便说一句,async 会使它变得更好,并且可以在 map 或 forEach 中使用。
  • @RobbyCornelissen 我已经用 Promise.all 的一些细节和对 async/await 的提示更新了我的答案。
猜你喜欢
  • 2016-08-31
  • 2020-07-21
  • 2018-11-26
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
相关资源
最近更新 更多