在下一个开始之前等待上一个承诺的Javascript Map? [英] Javascript Map that waits for previous promise before starting next?

查看:67
本文介绍了在下一个开始之前等待上一个承诺的Javascript Map?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这不在Array.map的范围内,但是我想等到上一项完成诺言之后再开始下一项.碰巧我需要等待之前的条目保存在数据库中,然后再继续前进.

I know this isn't in the scope of a Array.map but I'd like to wait until the previous item has finished its promise before starting the next one. It just happens that I need to wait for the previous entry to be saved in the db before moving forwards.

const statsPromise = stats.map((item) => {
    return playersApi.getOrAddPlayer(item, clubInfo, year); //I need these to wait until previous has finished its promise.
});

Promise.all(statsPromise)
.then((teamData) => {
  ..//
});

playersApi.getOrAddPlayer返回new Promise

修改

要详细了解它,向玩家展示Api.getOrAddPlayer似乎很重要

Reading more on it, it seems its important to show playersApi.getOrAddPlayer

getOrAddPlayer: function (item, clubInfo, year) {
    return new Promise((resolve, reject) => {

        var playerName = item.name.split(' '),
            fname = playerName[0].caps(),
            sname = playerName[1].caps();

                Players.find({
                    fname: fname,
                    sname: sname,
                }).exec()
                .then(function(playerDetails, err){
                    if(err) reject(err);
                    var savePlayer = new Players();
                    //stuff
                    savePlayer.save()
                    .then(function(data, err){
                        if(err)  reject(err);
                        item._id = data._id;
                        resolve(item);
                    });
                });
            });
}

推荐答案

您可以使用缩减而不是映射来实现此目的:

You can use reduction instead of mapping to achieve this:

stats.reduce(
  (chain, item) =>
    // append the promise creating function to the chain
    chain.then(() => playersApi.getOrAddPlayer(item, clubInfo, year)),
  // start the promise chain from a resolved promise
  Promise.resolve()
).then(() => 
  // all finished, one after the other
);

演示:

const timeoutPromise = x => {
  console.log(`starting ${x}`);
  return new Promise(resolve => setTimeout(() => {
    console.log(`resolving ${x}`);
    resolve(x);
  }, Math.random() * 2000));
};

[1, 2, 3].reduce(
  (chain, item) => chain.then(() => timeoutPromise(item)),
  Promise.resolve()
).then(() =>
  console.log('all finished, one after the other')
);

如果需要累加值,则可以通过归约传播结果:

If you need to accumulate the values, you can propagate the result through the reduction:

stats
  .reduce(
    (chain, item) =>
      // append the promise creating function to the chain
      chain.then(results =>
        playersApi.getOrAddPlayer(item, clubInfo, year).then(data =>
          // concat each result from the api call into an array
          results.concat(data)
        )
      ),
    // start the promise chain from a resolved promise and results array
    Promise.resolve([])
  )
  .then(results => {
    // all finished, one after the other
    // results array contains the resolved value from each promise
  });

演示:

const timeoutPromise = x => {
  console.log(`starting ${x}`);
  return new Promise(resolve =>
    setTimeout(() => {
      console.log(`resolving result for ${x}`);
      resolve(`result for ${x}`);
    }, Math.random() * 2000)
  );
};

function getStuffInOrder(initialStuff) {
  return initialStuff
    .reduce(
      (chain, item) =>
        chain.then(results =>
          timeoutPromise(item).then(data => results.concat(data))
        ),
      Promise.resolve([])
    )
}

getStuffInOrder([1, 2, 3]).then(console.log);

变化#1:Array.prototype.concat看起来更优雅,但将在每个串联中创建一个新数组.为了提高效率,您可以将Array.prototype.push与更多样板一起使用:

Variation #1: Array.prototype.concat looks more elegant but will create a new array on each concatenation. For efficiency purpose, you can use Array.prototype.push with a bit more boilerplate:

stats
  .reduce(
    (chain, item) =>
      chain.then(results =>
        playersApi.getOrAddPlayer(item, clubInfo, year).then(data => {
          // push each result from the api call into an array and return the array
          results.push(data);
          return results;
        })
      ),
    Promise.resolve([])
  )
  .then(results => {

  });

演示:

const timeoutPromise = x => {
  console.log(`starting ${x}`);
  return new Promise(resolve =>
    setTimeout(() => {
      console.log(`resolving result for ${x}`);
      resolve(`result for ${x}`);
    }, Math.random() * 2000)
  );
};

function getStuffInOrder(initialStuff) {
  return initialStuff
    .reduce(
      (chain, item) =>
        chain.then(results =>
          timeoutPromise(item).then(data => {
            results.push(data);
            return results;
          })
        ),
      Promise.resolve([])
    );
}

getStuffInOrder([1, 2, 3]).then(console.log);

变体2:您可以将results变量提升到上限.这样一来,无需嵌套函数即可在累积数据时通过最近的闭包使results可用,而使整个链全局可用.

Variation #2: You can lift the results variable to the upper scope. This would remove the need to nest the functions to make results available via the nearest closure when accumulating data and instead make it globally available to the whole chain.

const results = [];
stats
  .reduce(
    (chain, item) =>
      chain
        .then(() => playersApi.getOrAddPlayer(item, clubInfo, year))
        .then(data => {
          // push each result from the api call into the globally available results array
          results.push(data);
        }),
    Promise.resolve()
  )
  .then(() => {
    // use results here
  });

演示:

const timeoutPromise = x => {
  console.log(`starting ${x}`);
  return new Promise(resolve =>
    setTimeout(() => {
      console.log(`resolving result for ${x}`);
      resolve(`result for ${x}`);
    }, Math.random() * 2000)
  );
};

function getStuffInOrder(initialStuff) {
  const results = [];
  return initialStuff.reduce(
    (chain, item) =>
      chain
        .then(() => timeoutPromise(item))
        .then(data => {
          results.push(data);
          return results;
        }),
    Promise.resolve()
  );
}

getStuffInOrder([1, 2, 3]).then(console.log);

这篇关于在下一个开始之前等待上一个承诺的Javascript Map?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆