【问题标题】:How can i implement multiple promises inside a loop我如何在循环中实现多个承诺
【发布时间】:2019-05-08 12:18:45
【问题描述】:

我正在尝试使用 flicker 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 
  }

我怎样才能等待这个循环结束,然后才用新的滤镜图像更改当前数组?

【问题讨论】:

  • 您正在混合异步和同步代码。 Promise 是异步的,所以newFilterdImages.push(img); 将在this.setState({images:newFilterdImages}) 之后执行

标签: reactjs promise axios


【解决方案1】:

在 Javascript 中,Promise 代表了某个可能缓慢操作的未来结果。实现 Promise 的结果需要在其上运行 .then()

为了更容易等待一堆未来的结果,为您提供了方法Promise.all()。它接受一个 Promise 列表并返回一个 Promise,该 Promise 使用所有提供的 Promises 的未来值进行解析。

结合这些点,我们可以通过将图像列表映射到 Promise 列表来对所有图像运行 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) })
})

【讨论】:

    【解决方案2】:

    您需要使用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})
        })
      }
    

    【讨论】:

    • newFilterdImages.push(img); -> img is not defined
    • 你需要获取indexdata.forEach((item, index) {...然后将对应的图片推入数组newFilterdImages.push(currentImages[index]);
    • @OlivierBoissé 感谢您的评论。我更新了我的答案,没注意那个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 2014-02-04
    • 2020-05-15
    • 1970-01-01
    • 2021-10-02
    相关资源
    最近更新 更多