简体   繁体   English

仅在诺言解决时返回地图

[英]Return in a map only when promises resolve

I am using loadash map function to do some structuring of data. 我正在使用loadash映射功能来进行数据的结构化。 The data returns a set of ids for which i need to query the db and add the result to the map and then return but the data is returned later and my function returns first. 数据返回一组ID,我需要查询这些ID并将结果添加到地图中,然后返回,但是稍后返回数据,并且我的函数首先返回。 How to make the return of map wait and then return in function. 如何使地图返回等待然后返回功能。

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();

I also tried using promises 我也尝试过使用诺言

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);
    });

Update i have already listed the promise .all method that doesnot work . 更新我已经列出了行不通的promise.all方法。 So it cannot be called duplicate 所以它不能被称为重复

Things are slightly tricky because you have an outer .map() and an inner .map() , containing an asynchronous element. 事情有点棘手,因为您有一个包含异步元素的外部.map()和内部.map()

The asynchronous element effectively makes the whole thing asynchronous, requiring that : 异步元素有效地使整个事物变得异步,这要求:

  • the array of Promises generated by the inner .map() is aggregated with Promise.all(), and the aggregate Promise returned to the outer .map() . 内部.map()生成的Promises数组与Promise.all()聚合,并且聚合的Promise返回到外部.map()
  • the array of Promises generated by the outer .map() is aggregated with Promise.all(). 外部.map()生成的Promises数组将与Promise.all()聚合。
  • the results (an array of items) is available only via a chained .then() . 结果(一组项目)只能通过链接的.then()

First, to make the main code block simpler and easier to read, create a promisified version of dspAccount.findAsync() . 首先,要使主代码块更容易阅读,请创建dspAccount.findAsync()的允许版本。

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

Then the main code block can be written as follows : 然后可以将主代码块编写如下:

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
});

I expect there's still some work to do. 我希望还有很多工作要做。 It doesn't look right that item should be mutated in the item.targetting.map() loop. 应该在item.targetting.map()循环中对item进行item.targetting.map()似乎并不正确。 The last element of item.targetting to deliver its result (synch or asynch) will determine the composition of item . 用于传递结果的item.targetting的最后一个元素(同步或异步)将确定item的组成。 That may not be what you want. 那可能不是您想要的。 If it is what you want, then more control will need to be exercised to ensure that the last result delivered is the result arising from the final element of item.targetting . 如果这是您想要的,则需要进行更多控制,以确保最后传递的结果是item.targetting的最后一个元素产生的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM