'Return complete array from Promise

I have a function that returns JSON objects using hnews.getById(id). I then push each story returned in the promise to an array. I'm having trouble figuring out how I'd then get the complete array. Do I need to use another promise?

function updateTopStories() {
    var storiesArr = [];

    hnews.getIdsInCategory('topstories', 60)
    .then(function(ids) {
        ids.forEach(function(id) {
            hnews.getById(id).then(function(story) {
                console.log(story);
                storiesArr.push(story);
            });
        });
    });

    return storiesArr;
}

var stories = updateTopStories();
console.log(stories); // Empty array

EDIT: I need to return storiesArr from updateTopStories();



Solution 1:[1]

You are invoking multiple async processes here. A common way of handling this is to map your array of ids to an array of Promises which all have to resolve before returning. See if this works for you.

function updateTopStories() {

    return hnews.getIdsInCategory('topstories', 60).then(function(ids) {
        var promises = ids.map(function(id) {
            return hnews.getById(id);
        });
        return Promise.all(promises);
    });
}

updateTopStories().then(function(stories) {
    console.log(stories);
});

Solution 2:[2]

I am not very sure as I am not able to try this, but looks like you have scoping problem here, try to do this.

     function updateTopStories() {
        var tempStoriesArr = [];

        hnews.getIdsInCategory('topstories', 60)
        .then(function(ids) {
            ids.forEach(function(id) {
                hnews.getById(id).then(function(story) {
                    console.log(story);
                    tempStoriesArr.push(story);
                });
            });
        });
        return tempStoriesArr;
    }

    var StoriesArr = updateTopStories();
    console.log(StoriesArr);

Solution 3:[3]

You could reconstruct your response from each call as:

function updateTopStories() {
    var storiesArr = {};

    hnews.getIdsInCategory('topstories', 60)
    .then(function(ids) {
        ids.forEach(function(id) {
            storiesArr[id] = [];
            hnews.getById(id).then(function(story) {
                console.log(story);
                storiesArr[id].push(story);
            });
        });
    });
    return storiesArr;
}

updateTopStories();

Here you are initializing each story for a particular id group which is an array and then you can retrieve each story based on the id's.

Solution 4:[4]

You need to return the promise and return something from within the "then" block if you want to transform it. You can use Array.prototype.map to transform an array.

function updateTopStories() {
  return hnews.getIdsInCategory('topstories', 60)
    .then(function(ids) {
      return ids.map(function(id) {
        return hnews.getById(id).then(function(story) {
            console.log(story);
            return story;
        });
    });
  });
}

updateTopStories().then(function(arr) {
  arr.foreach(function(s) {
    console.log('Story:', s);
  });
});

Solution 5:[5]

Ok I got the idea:

function return_promise_array(para1):Promise<any>{
   return new Promise(async (resolve,reject)=>{
      var result=[];
      var level1=await get_promise_array();
      var process=[];
      for(var i=0;i<level1.length;i++){
        //after process the item, write the item result into result array 
        process.push(process_promise_item(level1[i],result));
      }
      //no way to run promise in for loop, 
      //but you can create promise function and add it into array,
      //then run it in Promise.all() 
      await Promise.all(process);  
      resolve(result);
   });
}
var result=[];
result=await return_promise_array(para1); //can return as array without error.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Mitesh Pant
Solution 3 Anirudh B
Solution 4
Solution 5 Fenix Lam