简体   繁体   中英

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 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://randomuser.me/api/').then(resp => resp.json()), fetch('https://randomuser.me/api/').then(resp => resp.json()), fetch('https://randomuser.me/api/').then(resp => resp.json()), fetch('https://randomuser.me/api/').then(resp => resp.json()), fetch('https://randomuser.me/api/').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
  }
*/

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM