javascript - 生成带有 promise 的数据集

标签 javascript node.js callback bluebird

我目前正在尝试使用 javascript 中的异步调用生成一个对数组,但我似乎无法按正确的顺序获取它。

generateDataPoints: function (iterable, source, arg) {
  let pairs = []
  let prevTime = 0
  for (let index in iterable) {
    let event = iterable[index]
    getTime(event.valueOf()).then(function (time) {
      query(source[arg], event.valueOf()).then(function(val) {
        if (time !== prevTime) {
          prevTime = time
          pairs.push([time, val])
          console.log(pairs) // This works as expected but only happens after the program returns
        } else {
          Promise.resolve()
        }
      })
    })
  }
  return Promise.resolve(pairs)
}

问题是“pairs.push..”命令在我返回后发生。我无法弄清楚到底出了什么问题以及如何同步此过程。如有任何帮助,我们将不胜感激。

最佳答案

您正在将同步代码(如 for 循环)与异步代码混合在一起。尝试这样的事情:

function generateDataPoints(iterable, source, arg) {
  let prevTime = 0
  [...iterable].reduce((promiseChain, event) => {
    let pairs;
    return promiseChain
      .then(p => {
        pairs = p;
        return Promise.all([
          getTime(event.valueOf()),
          query(source[arg], event.valueOf())
        ])
      })
      .then(([time, val]) => {
        if (time !== prevTime) {
          prevTime = time
          return pairs.concat([[time, val]]);
        } else {
          return pairs;
        }
      });
    })
  }, Promise.resolve([]));
}

这会将 iterable 简化为顺序 Promise 链,最终将包含所有对。

如果您的环境允许,您还可以将函数转换为异步函数,只需进行少量更改即可:

generateDataPoints: async function (iterable, source, arg) {
  let pairs = []
  let prevTime = 0
  for (let index in iterable) {
    let event = iterable[index]
    const [time, val] = await Promise.all([
      getTime(event.valueOf()),
      query(source[arg], event.valueOf())
    ]);
    if (time !== prevTime) {
      prevTime = time
      pairs.push([time, val])
    }
  }
  return pairs;
}

编辑:

仔细观察,您似乎不需要对这些 Promise 进行排序。您也许可以并行运行它们:

function generateDataPoints(iterable, source, arg) {
  Promise.all(
    [...iterable].map(event => Promise.all([
      getTime(event.valueOf()),
      query(source[arg], event.valueOf())
    ])
  ).then(pairs => {
    let prevTime = 0
    return pairs.filter(([time, val]) => {
      if (time !== prevTime) {
        prevTime = time;
        return true;
      } else {
        return false;
      } 
    });
  });
}

关于javascript - 生成带有 promise 的数据集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46897890/

相关文章:

javascript - 类型错误 : "callback" argument must be a function

javascript - 警报未出现在本地主机中

javascript - JQuery Ajax 未调用页面,但其他一切正常

javascript - Node Javascript 的这一行条件有什么问题?

node.js - 为什么我的异步代码在 Controller 中有效,而在模型中无效?

javascript - 循环响应的异步回调无序

javascript - 在日期选择器中禁用日历

javascript - 首先调用的同一事件目标的事件监听器

node.js - React Native 中的 Socket io

Javascript 回调超时