1

Firstly apologies if this is a simple problem to solve but I am using node-fetch and the concept of Promises for the first time. I am calling an api endpoint which returns paginated data so i get multiple links for further data.

I am handling this by putting all the links into an array and then I want to call each endpoint in the array and just print out the data to the console for now

So my first call is

var urlArray = [];

fetch(`${BASE_URL}/leagues?api_token=${AUTH_TOKEN}`, { headers: headers })
.then(function(response){
  return response.json(); // pass the data as promise to next then block
})
.then(function(json){

  // Collect Paginated Results
  var number_of_pages = parseInt(json.meta['pagination']['total_pages']);
  for (i = 2; i < number_of_pages + 1; i++) {
    urlArray.push(`${BASE_URL}?page=${i}&api_token=${AUTH_TOKEN}`)
  }
})
.catch(function(error) {
  console.log(error);
});

So once this done i have an array of urls i need to hit sequentially, could anyone give me some pointers please on how to then setup a promise to hit each one? or can i have something where is do it in my for loop?

Thanks

Richlewis
  • 15,070
  • 37
  • 122
  • 283
  • Possible duplicate of [Resolve promises one after another (i.e. in sequence)?](https://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-i-e-in-sequence) – alexmac Oct 04 '17 at 09:26
  • Make a function that takes one url as an argument, and returns a promise for the desired result(s). Then call it recursively. – Bergi Oct 04 '17 at 10:15

3 Answers3

0

sorry if this is wrong!

At the beginning, put:

var promise_array = [];

in the for loop, replace with

for (i = 2; i < number_of_pages + 1; i++) {
  var url = `${BASE_URL}?page=${i}&api_token=${AUTH_TOKEN}`;
  urlArray.push(url);
  promise_array.push(fetch(url));
}

At the end of the function put

Promise.all(promise_array).then(all_responses => {
   // .. pluck json, then continue ...
});
0

You can use Array.prototype.reduce to create Promise chain so they will be executed one after another

urls.reduce((prev, item) => {
    return prev.then(() => {
        return someAction(item);
    })
}, Promise.resolve()).then(() => {
    console.log('All done');
}).catch((err) => {
    console.log(err);
});

Edit:

As mentioned by Bergi, value from someAction should be returned in case it's asynchronous (return Promise). If someAction is asynchronous it must return Promise.

"use strict";
function someAction(i) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   console.log(i);
   resolve(i);
  }, i*1000);
 });
}
const urls = [1,2,3,4,5];
urls.reduce((prev, item) => {
 return prev.then(() => {
  return someAction(item);
 })
}, Promise.resolve()).then(() => {
 console.log('All done');
}).catch((err) => {
 console.log(err);
});
ponury-kostek
  • 7,824
  • 4
  • 23
  • 31
  • This will still run all `someAction`s concurrently if they are asynchronous, not waiting for the previous one. – Bergi Oct 04 '17 at 10:16
0

You can achieve this by:

fetch(`${BASE_URL}/leagues?api_token=${AUTH_TOKEN}`, { headers: headers }).then(response => {
    var json = response.json();
    var numberOfPages = parseInt(json.meta['pagination']['total_pages']);
    var urlArray = [];
    for (i = 2; i < numberOfPages + 1; i++) {
      urlArray.push(`${BASE_URL}?page=${i}&api_token=${AUTH_TOKEN}`)
    }  
    var promises = urlArray.map(url => getSomethingByUrl(url));
    return Promise.all(promises);
}).then(results => {  
    console.log(results); 
});
Faly
  • 13,291
  • 2
  • 19
  • 37