Reactjs 如何在一个循环中实现多个承诺

Reactjs 如何在一个循环中实现多个承诺,reactjs,promise,axios,Reactjs,Promise,Axios,我正在尝试使用flicker getinfo请求按标题或描述过滤图像,该请求返回此信息 我试图做的是为当前图像数组中的每个图像发送一个getinfo请求,查看标题或描述是否与用户输入匹配,如果匹配,则呈现这个新的过滤图像数组 我无法解决如何调用每个图像,只有在循环结束并完成过滤数组后,才能对该数组调用setState filterImages = (filter) =>{ if(filter.length === 0) return; const cur

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

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

在Javascript中,承诺表示可能缓慢操作的未来结果。实现承诺的结果需要在其上运行
。然后()

为了更方便地等待未来的结果,我们为您提供了方法
Promise.all()
。它获取承诺列表并返回一个承诺,该承诺与所有提供的承诺的未来值进行解析

结合这些要点,我们可以通过将图像列表映射到承诺列表,在所有图像上运行
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()
,并将其视为一个Promise,当所有结果都可用时,它将与来自
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) })
})

在Javascript中,承诺表示可能缓慢操作的未来结果。实现承诺的结果需要在其上运行
。然后()

为了更方便地等待未来的结果,我们为您提供了方法
Promise.all()
。它获取承诺列表并返回一个承诺,该承诺与所有提供的承诺的未来值进行解析

结合这些要点,我们可以通过将图像列表映射到承诺列表,在所有图像上运行
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()
,并将其视为一个Promise,当所有结果都可用时,它将与来自
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) })
})

您正在混合异步和同步代码。承诺是异步的,这样做
newFilterdImages.push(img)
将在
this.setState({images:newFilterdImages})之后执行。
您正在混合异步和同步代码。承诺是异步的,这样做
newFilterdImages.push(img)
将在
this.setState({images:newFilterdImages})
newFilterdImages.push(img)之后执行
->
img未定义
您需要获取索引
数据。forEach((项,索引){…
然后在数组中推送相应的图像
newFilterdImages.push(currentImages[index]);
@OlivierBoissé谢谢您的评论。我更新了我的答案,没有注意
newFilterdImages.push(img)
->
img未定义
您需要获取索引
数据。forEach((项,索引){…
然后在数组中推送相应的图像
newfilterImages.push(currentImages[index]);
@OlivierBoissé谢谢您的评论。我更新了答案,没有注意到这一点