簡體   English   中英

一旦所有嵌套的promises都已解決,就使用Fire Promise.all()

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM