[英]Fire Promise.all() once all nested promises have resolved
我正在嘗試使用他們的Firebase API以遞歸方式獲取Hacker News故事的所有評論。 故事有一個kids
屬性,它是一組代表注釋的ID。 每個評論都可以有自己的kids
屬性,指向孩子的評論,等等。 我想創建一個整個注釋樹的數組,看起來像這樣:
[{
'title': 'comment 1',
'replies': [{
'title': 'comment 1.1'
}, {
'title': 'comment 1.2'
'replies': [{
'title': 'comment 1.2.1'
}]
}]
}]
我以為我可以使用以下功能執行此操作:
function getItem(id) {
return api
.child(`item/${id}`)
.once('value')
.then((snapshot) => { // this is a Firebase Promise
let val = snapshot.val()
if (val.kids) {
val.replies = val.kids.map((id) => getItem(id))
}
return val
})
}
然后在使用以下內容獲取整個評論樹后收到通知:
getItem(storyId)
.then(story => {
// The story and all of its comments should now be loaded
console.log(story)
})
最終發生的是Promise.all().then()
在第一級評論承諾解決后觸發(這是有道理的,因為所有的commentPromises
已經解決了。)但是,我想知道一旦所有嵌套的承諾都解決了。 我怎樣才能做到這一點?
在其他答案中不需要包裝器承諾; 這就是“ 顯式承諾構造函數反模式 ”。 簡化一點,您可以執行以下操作:
function getItem(id) {
return api
.child(`item/${id}`)
.once('value')
.then(snapshot => {
const val = snapshot.val();
return Promise.all((val.kids || []).map(getItem))
.then(kidsVals => {
val.replies = kidsVals;
return val;
});
);
});
}
也不需要任何明確的拒絕處理。 拒絕會自然地傳播到頂層(假設這是你想要的)。
IMP:請參考azaburo的回答。 它比我好多了。
=========
我認為這應該有效:
function getItem(id) {
return new Promise(function(resolve, reject) {
api
.child(`item/${id}`)
.once('value')
.then((snapshot) => { // this is a Firebase Promise
let val = snapshot.val()
if (val.kids) {
let replies = val.kids.map((id) => getItem(id))
Promise.all(replies).then(replies => {
val.replies = replies // <<<<<< try this
resolve(val) // we want to resolve val, not val.replies
}, err =>{
reject(err)
})
} else {
resolve(val)
}
})
.catch((err) => { // if there was some error invoking api call we need to reject our promise
reject(err);
})
}
}
編輯: then
在里面設置val.replies
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.