Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fetch multiple URLs at the same time?

I'm looking for a way to fetch multiple URLs at the same time. As far as I know the API can only retrieve the data I want with a single product lookup so I need to fetch multiple products at once with the url structure "/products/productID/". Note, this is in VUEJS. This is what my code looks like so far:

In my productServices.js:

const productsService = {
 getCategory(productID){
    const url = `${config.apiRoot}/products/${productID}`

    return fetch(url, {
    method: 'GET',
    headers: {
        'content-type': 'application/json',
        'Authorization': `Bearer ${authService.getToken()}`
    },
    })
 }
}

In my view:

data() {
  return {
    featuredProduct: [13,14,15],
    productName: [],
    productImg: []
  }
}
async mounted(){
    const response = await productsService.getCategory(this.featuredProduct)
    const resJSON = JSON.parse(response._bodyInit)
    this.loading = false
    this.productName = resJSON.name
    this.productImg  = resJSON.custom_attributes[0].value
}

So I need to hit all three featuredProduct IDs and store the data. I'm not really sure how to loop through multiple URLS. All of my other API calls have had all the data readily available using search params but for the specific data I need here ( product image ), it can only be seen by calling a single product.

Any help is much appreciated!

like image 223
user3330820 Avatar asked Nov 25 '19 17:11

user3330820


3 Answers

Like Ricardo suggested I'd use Promise.all. It takes in an array of promises and resolves the promise it returns, once all the passed ones have finished (it resolves the promises in the form of an array where the results have the same order as the requests).

Docs

Promise.all([
  fetch('https://jsonplaceholder.typicode.com/todos/1').then(resp => resp.json()),
  fetch('https://jsonplaceholder.typicode.com/todos/2').then(resp => resp.json()),
  fetch('https://jsonplaceholder.typicode.com/todos/3').then(resp => resp.json()),
]).then(console.log)

Using map + Promise.all (tested)

Promise.all([1, 2, 3].map(id => 
  fetch(`https://jsonplaceholder.typicode.com/todos/${id}`).then(resp => resp.json())
)).then(console.log);

if you have multiple products in an array which need to be fetched, you could just use:

Code not tested

Promise.all(productIds.map(productId => 
  fetch(`https://url/products/${productId}`)
)).then(() => {/* DO STUFF */});

Little suggestion on storing your data:

If you store everything in one array, it makes to whole job way easier. So you could do

fetchFunction().then(results => this.products = results);

/*
  this.products would then have a structure something like this:
  Array of Obejcts: {
    name: "I'm a name",
    displayName: "Please display me",
    price: 10.4
    // And so on
  }
*/
like image 189
Elias Avatar answered Nov 02 '22 19:11

Elias


Because you have an array of products, I'd start by changing your state names:

data() {
  return {
    productIds: [13, 14, 15],
    productNames: [],
    productImages: [],
  };
},

Then you can use Promise.all to fetch the products in parallel:

async mounted() {
  const responses = await Promise.all(
    this.productIds.map(id => productsService.getCategory(id))
  );
  responses.forEach((response, index) => {
    const resJSON = JSON.parse(response._bodyInit);
    this.productNames[index] = resJSON.name;
    this.productImages[index] = resJSON.custom_attributes[0].value;
  });

  this.loading = false;
}

You could also consider refactoring getCategory do the parsing for you and return an object containing a name and an image - that way, mounted wouldn't have to know about the internal response structure.

like image 3
David Weldon Avatar answered Nov 02 '22 19:11

David Weldon


Check the Promise.all method

Maybe you can create the calls that you need by iterating into your data and then request them in bulk.

like image 2
Ricardo Gonzalez Avatar answered Nov 02 '22 19:11

Ricardo Gonzalez