Fire Promise.all () after all nested promises are resolved

I am trying to recursively get all comments on hacker history using their Firebase API. The story has a kids property, which is an array of identifiers representing comments. Each comment can have its own kids property, which indicates its comments on children, etc. I want to create an array of the entire comment tree, something similar:

 [{ 'title': 'comment 1', 'replies': [{ 'title': 'comment 1.1' }, { 'title': 'comment 1.2' 'replies': [{ 'title': 'comment 1.2.1' }] }] }] 

I thought I could do this using the following function:

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

And then get notified after receiving the whole comment tree with:

 getItem(storyId) .then(story => { // The story and all of its comments should now be loaded console.log(story) }) 

As a result, Promise.all().then() triggered after resolving the first level of the promises comment (which makes sense since all commentPromises resolved.) However, I want to know as soon as all the nested promises have resolved. How can i do this?

+5
source share
2 answers

There is no need to promise a wrapper, as in other answers; that is, the " explicit promise constructor mechanism . By ordering a little more, you can do the following:

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

There is also no need for any explicit failure handling. Deviations will naturally propagate to the upper level (assuming what you want).

+7
source

IMP: Please refer to torazaburo. This is much better than mine.

==========

I think this should work:

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

Edit: Setting val.replies inside then

+3
source

Source: https://habr.com/ru/post/1263484/


All Articles