2017-08-02 100 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