Return complete array from Promise

2019-07-27 05:32发布

问题:

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

2nd EDIT: I'm an idiot. getById is returning a Promise. I think it's time I go to bed. Would a mod please delete this?

I can take it from here. Thanks all for looking.

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


回答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);


回答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.



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


回答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.