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
}
我如何等待此循环结束,然后才使用新的“过滤器图像”更改当前数组?
答案 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) })
})