【问题标题】:Node JS nested Promise.all and map logic not working节点 JS 嵌套 Promise.all 和映射逻辑不起作用
【发布时间】:2018-01-09 23:52:31
【问题描述】:

我正在尝试让嵌套的 Promise.all * 映射逻辑工作。当我到达 getData2 时,我不断收到未定义的值。

exports.getData = (param1, param2) => {
  return getData0(param1, param2)
    .then(data0 => Promise.all(data0.map(e => getData1(e.id))))
    .then(data1 => Promise.all(data1.map(i => getData2(i.id))))
    .then(data2 => data2.map(a => getData3(a.id)))
    .catch(err => console.error(err.message));
};

附注: 1. getData0 到 getData1 返回结构(例如 { a: val1, b: val2 }) 2. 我认为问题出在 getData 的编写方式上。我怀疑他们应该回报承诺。谁能给我一个关于返回结构的函数的虚拟示例,其中(参见上面的 a 和 b)的两个元素都是以异步方式获得的?

谢谢!

【问题讨论】:

  • getData1()getData2()getData3() 是异步操作吗?如果是这样,他们应该在异步操作完成时返回一个用结果解决的承诺。也很好奇为什么你将Promise.all()data0.map()data1.map() 一起使用,而不是与data2.map() 一起使用。如果它们不是异步操作,那么没有必要对它们使用Promise.all()。实际上,您可以将所有顺序同步代码合并到一个 .then() 处理程序中。
  • 如果你向我们展示你的实际代码(不是伪代码),Stackoverflow 会更好地工作,我们会帮助你修复它,而不是你要求我们编写可能会或可能不会教你实际需要的示例。因此,请向我们展示getData1()getData2()getData3() 的实际代码,您可能会得到非常有用和具体的帮助。
  • 我知道这一点,但有时在发布代码 sn-p 之前先弄清概念会更容易。 Dhruv 的回复解释了我不确定的不同概念。另外,我添加了一个答案来总结解决方案。
  • 没有。如果您包含实际代码,堆栈溢出会更好地工作 - 总是。如果没有您的实际代码,我们只能猜测如何最好地回答对您而言真正重要的问题。而且,通过您的实际代码,我们有机会向您展示更好的方法来做您自己不会想到的事情,甚至可能不知道要问什么。所以,最好“先搞清楚概念”。最好在实际代码的确切上下文中阐明概念。我用代码和概念解释发布答案。
  • 当然是Kentoj

标签: javascript node.js promise nested es6-promise


【解决方案1】:

首先,如果您的所有getData* 方法正在执行任何异步操作,它们都应该返回Promise 对象。 (例如获取数据)。

getData3 可能是一个例外,因为在所有 getData3 调用完成后,它看起来不需要做任何事情。 如果不是这种情况,您可以对getData3 使用与上述类似的方法。 例如data2 => Promise.all(data2.map(a => getData3(a.id)))

现在让我们逐行查看代码

exports.getData = (param1, param2) => {
  return getData0(param1, param2)
    .then(data0 => Promise.all(data0.map(e => getData1(e.id))))
    // data0 here should be an Array

    .then(data1 => Promise.all(data1.map(i => getData2(i.id))))

    // 1. data1 will be an Array with results from each getData1 call
    //    mapped by index. for e.g [result1, result2, ...]
    // 2. depending on the type of result (Object/Array) from getData1
    //    you should extract `id` from `i`(result item) and then 
    //    trigger `getData2`using that `id`. I'm assuming the issue is 
    //    here. 

    .then(data2 => data2.map(a => getData3(a.id)))
    .catch(err => console.error(err.message));
};

至于Can anyone give me a dummy example about a function that returns a structure wherein both elements of the (see a and b above) are obtained in an async way? 我相信这应该回答How to use Promise.all with an object as input

【讨论】:

  • 将您的答案标记为有效答案,因为它涵盖了我描述的逻辑中涉及的不同概念 - 请在下面查看我的新答案
【解决方案2】:

我已将 Dhruv 的答案标记为有效答案,因为它解释了我所描述的逻辑中涉及的不同概念。

getData1 和 getData2 确实在 getData3 同步时调用异步函数(在我的例子中:doSomeEWSwork 下面)。

function doSomeEWSwork(param) {

  var ewsFunction = '.....';
  var ewsArgs = ....;

  return ews.run(ewsFunction, ewsArgs)
    .then(result => result.something)
    .catch(err => console.log(err.message));
}

我的旧 getData1 和 getData2 用于返回结构对象(例如 {a: val1, b: val2} 而不是 Promise(Promise.all 需要)。这导致异步块永远不会执行/评估。

我的新 getData1 和 getData2 具有以下骨架:

function getData1_or_2(param) {

  var promise = new Promise(function(resolve, reject) {
    doSomeEWSwork(param) // <- important: settle this using 'then'
    .then(res => {
      var ret = { a: res.val1, b: res.val2 };
      resolve(ret);
    }).catch(err => {
      console.log(err.message);
      reject(Error(err.message));
    });
  });
  return promise;
}

所以 main 方法(已经包含在我的原始问题中)现在可以正常工作,因为我返回了异步的承诺和同步的对象。

exports.getData = (param1, param2) => {
  return getData0(param1, param2)
    .then(data0 => Promise.all(data0.map(e => getData1(e.id))))
    .then(data1 => Promise.all(data1.map(i => getData2(i.id))))
    .then(data2 => data2.map(a => getData3(a.id)))
    .catch(err => console.error(err.message));
};

只是嵌套 promise、map 和结构对象的组合让我感到困惑。 谢谢!

【讨论】:

  • 仅供参考,这种类型的构造 .catch(err =&gt; console.log(err.message)); 将“吃掉”拒绝而不传播它。当您 .catch() 拒绝并且不重新抛出它时,它会被视为“已处理”,就像在 try/catch() 中一样,并且承诺将更改为已解决。因此,如果您打算只记录错误并仍然传播拒绝,则必须rethrow.catch(err =&gt; {console.log(err.message); throw err;}); 因此,您的代码如图所示记录拒绝并将它们转换为具有undefined 已解决值的已解决承诺。
  • 是的,我很熟悉这个概念。那是一个测试代码,我对控制台日志更感兴趣。谢谢。
猜你喜欢
  • 1970-01-01
  • 2018-05-11
  • 2014-09-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
  • 2017-06-16
  • 1970-01-01
相关资源
最近更新 更多