【问题标题】:Return in a map only when promises resolve仅在承诺解决时才返回地图
【发布时间】:2018-05-18 05:06:58
【问题描述】:

我正在使用 loadash map 函数对数据进行一些结构化。数据返回一组 id,我需要为其查询 db 并将结果添加到地图然后返回,但数据稍后返回,我的函数首先返回。如何让map的返回等待然后在函数中返回。

let result = _.chain(value)
        .groupBy('pubId')
        .pairs()
        .map(function(currentItem) {
          let item =  _.object(_.zip(['ID', 'targetting'], currentItem));
          propsToBeDeleted.forEach(function(prop) {
            item.targetting.forEach(d => {
              item.publishername = d.RTB.name;
              item.type = d.type;
              delete d[prop];
            });
          });
          item.targetting.map(d => {
            if (d.type == 15) {
              d.name = Object.keys(JSON.parse(d.value));
              d.value = Object.values(JSON.parse(d.value))[0];
              item.dspIds = [];
            }
            if (d.type == 16) {
              let value = JSON.parse(d.value);
              d.name = Object.keys(JSON.parse(d.value)).filter(d => d != 'profileId');
              d.value = value;
              item.dspIds = d.value.profileId;
              dspAccount.find({where: {id: 139}}, (err, data) => {
                // async call wait here to get data and attach to item 
                 item.x = data ;
              });
              delete d.value.profileId;
              d.value = JSON.stringify(d.value);
            }
          });
          return item;
        })
        .value();

我也尝试过使用承诺

promises.push(new Promise((resolve, reject) => {
        if (data.id) {
          XX.upsertWithWhere({id: data.id}, payload, (err, data) => {
            if (err) {
              return reject(err);
            }
            return resolve(data);
          });
        }
      }));
    });
    Promise.all(promises).then((data) => {
      callback(null, data);
    }, err => {
      callback(err);
    });

更新 我已经列出了无效的 promise .all 方法。所以不能叫重复

【问题讨论】:

  • @VipinKumar 我已经列出了无效的 promise .all 方法。所以不能叫重复
  • 我想,我说过这是一个可能的重复而不是重复。检查重复是第一件事。请不要在您的问题中标记任何人。
  • 你能检查一下吗,如果你能帮忙的话会很高兴
  • 你使用的是哪个 node.js 版本?

标签: javascript node.js promise es6-promise


【解决方案1】:

事情有点棘手,因为您有一个外部.map() 和一个内部.map(),其中包含一个异步元素。

异步元素有效地使整个事情异步,要求:

  • 内层.map()生成的Promise数组用Promise.all()聚合,聚合后的Promise返回到外层.map()
  • 由外部.map() 生成的 Promise 数组与 Promise.all() 聚合。
  • 结果(项目数组)只能通过链接的.then() 获得。

首先,为了使主代码块更简单、更易于阅读,创建一个dspAccount.findAsync() 的承诺版本。

dspAccount.findAsync = function(query) {
    return new Promise(function(resolve, reject) {
        dspAccount.find(query, (err, data) => {
            if(err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
    });
}

那么主代码块可以写成如下:

let outerPromises = _.chain(value)
.groupBy('pubId')
.pairs()
.map(function(currentItem) {
    let item = _.object(_.zip(['ID', 'targetting'], currentItem));
    item.targetting.forEach(d => {
        item.publishername = d.RTB.name;
        item.type = d.type;
        propsToBeDeleted.forEach(function(prop) {
            delete d[prop];
        });
    });
    let innerPromises = item.targetting.map(d => {
        let value = JSON.parse(d.value);
        if (d.type == 15) { // synchronous - `innerPromises` receives a null
            item.dspIds = []; // 
            d.name = Object.keys(value);
            d.value = Object.values(value)[0];
            return null;
        }
        if (d.type == 16) { // asynchronous - `innerPromises` receives a Promise
            return dspAccount.findAsync({where: {id: 139}})
            .then(data => {
                d.name = Object.keys(value).filter(d => d != 'profileId');
                item.dspIds = value.profileId;
                delete value.profileId;
                item.x = data;
                d.value = JSON.stringify(value);
            });
        }
    });
    return Promise.all(innerPromises).then(() => item); // aggregate inner promises and return
})
.value(); //  returns the outerPromises array

Promise.all(outerPromises)  // aggregate outer promises
.then(items => {
    // do stuff with items here
})
.catch(error => {
    // something went wrong
    // log/display error 
    // take remedial action as required
});

我预计还有一些工作要做。 item 应该在 item.targetting.map() 循环中发生突变,这看起来不正确。 item.targetting 传递其结果的最后一个元素(同步或异步)将决定 item 的组成。那可能不是你想要的。如果这是您想要的,则需要进行更多控制,以确保交付的最后一个结果是由item.targetting 的最后一个元素产生的结果。

【讨论】:

    猜你喜欢
    • 2019-06-15
    • 2022-01-18
    • 2021-05-25
    • 1970-01-01
    • 2017-05-09
    • 2016-08-19
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多