2017-08-02 57 views
-1

我想获得一个嵌套的Promise.all *地图逻辑工作。当我到达getData2时,我总是收到未定义的值。节点JS嵌套Promise.all和地图逻辑不工作

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

P.S: 1. getData0到getData1回路结构(例如{A:VAL1,B:VAL2}) 2.我假定这个问题是在的getData的写入方式。我怀疑他们应该回复承诺。任何人都可以给我一个关于函数的虚拟示例,它返回一个结构,其中(见上面的a和b)的两个元素都是以异步方式获得的?

谢谢!

+1

是'getData1()','getData2()'和'getData3()'异步操作?如果是这样,那么他们应该返回一个在异步操作完成时用他们的结果解决的承诺。还好奇你为什么使用带有'data0.map()'和'data1.map()'的'Promise.all()',而不是'data2.map()'。如果它们不是异步操作,那么就不需要对它们使用'Promise.all()'。实际上,您可以将所有顺序同步代码组合到一个'.then()'处理程序中。 – jfriend00

+1

如果您向我们展示您的实际代码(而非伪代码),并且我们帮助您解决问题,而不是要求我们编写可能会或可能不会教您实际需要的示例,则Stackoverflow会更好。因此,请向我们展示'getData1()','getData2()'和'getData3()'的实际代码,您可能会获得非常有用的帮助。 – jfriend00

+0

我意识到这一点,但有时在发布代码片段之前,先澄清概念会更容易。德鲁夫的回答解释了我不确定的不同概念。另外,我添加了一个答案来总结解决方案。 – Hochman7G

回答

2

首先,你所有的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

+0

标记你的答案是有效的答案,因为它涵盖了我描述的逻辑中涉及的不同概念 - 检查我的新答案低于 – Hochman7G

0

我标志着Dhruv直升机的回答为有效之一,因为它解释了我描述的逻辑中涉及的不同概念。

getData1和getData2确实会调用异步函数(在我的情况下:doSomeEWSwork在下面),而getData3是同步的。

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

那么既然我为异步和对象同步返回承诺的主要方法(已经包括在我原来的问题)现在的工作罚款

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

这只是嵌套的承诺,地图和结构对象的混合使我困惑。 谢谢!

+0

仅供参考,这种类型的结构'.catch(err => console.log(err.message ));'会“吃”拒绝,不传播它。当'.catch()'拒绝并且不重新抛出它时,它就像'try/catch()'一样被认为是“处理过的”,并且promise被更改为解决。所以,如果你打算只记录错误并且仍然传播拒绝,你必须'rethrow':'.catch(err => {console.log(err.message); throw err;});'所以,你的如图所示的代码将记录拒绝并将其转化为已解决的承诺,并具有未定义的解析值。 – jfriend00

+0

是的,我对这个概念很熟悉。这是一个测试代码,我对控制台日志更感兴趣。谢谢。 – Hochman7G