如何在循环内实现多个承诺

时间:2019-05-08 12:18:46

标签: reactjs promise axios

im尝试使用闪烁的getinfo请求按标题或描述过滤图像,该请求会返回此信息。

我想做的是为当前图像数组中的每个图像发送一个getinfo请求,查看标题或描述是否与用户输入匹配,如果是,则渲染此新的过滤图像数组。

我无法解析应该如何为每个图像进行调用,只有在循环结束并完成过滤后的数组之后,才在该数组上调用setState。


  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 
  }

我如何等待此循环结束,然后才使用新的“过滤器图像”更改当前数组?

2 个答案:

答案 0 :(得分:1)

您需要使用Promise.all()等待所有图像解析,然后再对其进行过滤并分配给状态

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})
    })
  }

答案 1 :(得分:1)

在Javascript中,Promise表示将来可能由于操作缓慢而产生的结果。实现承诺的结果涉及在其上运行.then()

为了更轻松地等待将来的结果,我们为您提供了方法Promise.all()。它接受一个Promises列表,并返回一个Promise,该Promise将使用所有提供的Promises的将来值来解决。

结合这些点,我们可以通过将图像列表映射到承诺列表来对所有图像运行axios

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'
  })
})

...然后在结果列表上运行Promise.all(),并将其视为一个承诺,当它们全部可用时,将根据axios()的结果列表进行解析:

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) })
})