How can i implement multiple promises inside a loop

冷暖自知 提交于 2019-12-13 04:25:03

问题


im trying to filter images by title or description using flicker getinfo request, which returns this information.

what I'm trying to do is to send a getinfo request for each image inside currently images array, see if the title or description match the user input and if so to render this new filtered images array.

I cannot resolve how should I make a call for each image, and only after the loop is over and the filtered array is done, then call setState on that array.


  filterImages = (filter) =>{
    if(filter.length === 0)
      return;

    const currentImages = this.state.images;
    console.log(currentImages[0]);
    const newFilterdImages =[];
    const baseUrl = 'https://api.flickr.com/';

    for (const img of currentImages){
      axios({
      url: `services/rest/?method=flickr.photos.getinfo&api_key=22c1f9009ca3609bcbaf08545f067ad&photo_id=${img.id}&&format=json&safe_search=1&nojsoncallback=1`,
      baseURL: baseUrl,
      method: 'GET'
    })
    .then(res=> res.data)
    .then(res=> {
      if( res && res.photo) {
        const imageInfo = res.photo;
        //console.log(imageInfo.title._content,imageInfo.description._content);

        if(imageInfo.title._content.includes(filter) || imageInfo.description._content.includes(filter)){
            newFilterdImages.push(img);
        }
      }
    }).then( res => console.log("first then " + newFilterdImages)) // output the newFilterdImages array on each call
    }

    this.setState({images:newFilterdImages}) // this will not work 
  }

how can i wait for this loop to end, and only then change the current array with new Filter Images?


回答1:


In Javascript, a Promise represents some future result of a possibly slow operation. Realizing the result of a Promise involves running .then() on it.

To make it easier to wait for a bunch of future results, the method Promise.all() is provided for you. It takes a list of Promises and returns a Promise that resolves with the future values of all of the provided Promises.

Combining these points, we can run axios on all of the images by mapping the list of images to a list of Promises:

let axioses = currentImages.map((img) => {
  return axios({
      url: `services/rest/?method=flickr.photos.getinfo&api_key=22c1f9009ca3609bcbaf08545f067ad&photo_id=${img.id}&&format=json&safe_search=1&nojsoncallback=1`,
      baseURL: baseUrl,
      method: 'GET'
  })
})

...and then running Promise.all() on the resulting list and treating it as a promise that resolves with a list of results from axios() when they're all available:

Promise.all(axioses).then((results) => {
      const filteredResults = results.filter((res) => {
         if (!res || !res.photo) {
            return false
         }

         const imageInfo = res.photo;

         return imageInfo.title._content.includes(filter) || imageInfo.description._content.includes(filter))
     )

     this.setState({ images: filteredResults.map(res => res.photo) })
})



回答2:


You need to make use of Promise.all() to wait for all the images to resolve before filtering them and assigning to state

filterImages = (filter) =>{
    if(filter.length === 0)
      return;

    const currentImages = this.state.images;
    console.log(currentImages[0]);
    const newFilterdImages =[];
    const baseUrl = 'https://api.flickr.com/';
    const promises = [];
    for (const img of currentImages){
      promises.push(axios({
      url: `services/rest/?method=flickr.photos.getinfo&api_key=22c1f9009ca3609bcbaf08545f067ad&photo_id=${img.id}&&format=json&safe_search=1&nojsoncallback=1`,
      baseURL: baseUrl,
      method: 'GET'
    })
    .then(res=> res.data)
    }
    Promise.all(promises).then((data) => {
        data.forEach((item, index) => {
             if( item && item.photo) {
                 const imageInfo = res.photo;
                 if(imageInfo.title._content.includes(filter) || imageInfo.description._content.includes(filter)){
                       newFilterdImages.push(currentImages[index]);
                 }
             }
        });
        this.setState({images:newFilterdImages})
    })
  }


来源:https://stackoverflow.com/questions/56040643/how-can-i-implement-multiple-promises-inside-a-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!