我有一个场景,我正在调用一个具有分页的 API。 我想做的是以下内容,一次一页。
- 调用 API 第 1 页
- 对于响应中的每个项目,调用 Promise 以获取更多数据并存储在数组中
- 将数组发送到 API
- 重复直到所有页面都完成
我目前拥有的是以下内容,但我认为我可能将其复杂化了太多,尽管不确定如何进行。
export const importData = async() {
const pSize = 15;
const response = await getItems(pSize, 1);
const noPage = Math.ceil(response.totalMerchandiseCount/pSize);
for (let i = 1; i < noPage; i++) {
const items = [];
const data = await getItems(pSize, i);
await async.each(data.merchandiseList, async(i, cb) => {
const imageURL = await getImageURL(i.id, i.type);
items.push({
id: i.id,
imageURL: imageURL,
});
cb();
}, async() => {
return await api.mockable('sync', items);
});
}
}
export const getImageURL = async(id, type) => {
let url = `https://example.com/${id}`;
return axios.get(url)
.then((response) => {
const $ = cheerio.load(response.data);
// do stuff to get imageUrl
return image;
})
.catch((e) => {
console.log(e);
return null;
})
};
我目前遇到的问题是,它似乎要等到所有页面都完成后再调用 api.mockable。此时项目也是空的。
任何人都可以建议一种使它更整洁并帮助我让它工作的方法吗?
最佳答案
如果这一切都是串行的,那么您可以使用 for-of
循环:
export const importData = async() {
const pSize = 15;
const response = await getItems(pSize, 1);
const noPage = Math.ceil(response.totalMerchandiseCount/pSize);
for (let i = 1; i < noPage; i++) { // Are you sure this shouldn't be <=?
const items = [];
const data = await getItems(pSize, i);
for (const {id, type} of data.merchandiseList) {
const imageURL = await getImageURL(id, type);
items.push({id, imageURL});
}
await api.mockable('sync', items);
}
}
我还在其中添加了一些解构和速记属性。 :-)
如果只是串行的页面,但你可以并行获取项目,你可以将for-of
替换为map
和Promise.all
在项目上:
export const importData = async() {
const pSize = 15;
const response = await getItems(pSize, 1);
const noPage = Math.ceil(response.totalMerchandiseCount/pSize);
for (let i = 1; i < noPage; i++) { // Are you sure this shouldn't be <=?
const data = await getItems(pSize, i);
const items = await Promise.all(data.merchandiseList.map(async ({id, type}) => {
const imageURL = await getImageURL(id, type);
return {id, imageURL};
}));
await api.mockable('sync', items);
}
}
async
函数调用 map
作为非async
函数可以稍微更高效:
export const importData = async() {
const pSize = 15;
const response = await getItems(pSize, 1);
const noPage = Math.ceil(response.totalMerchandiseCount/pSize);
for (let i = 1; i < noPage; i++) {
const data = await getItems(pSize, i);
const items = await Promise.all(data.merchandiseList.map(({id, type}) =>
getImageURL(id, type).then(imageURL => ({id, imageURL}))
));
await api.mockable('sync', items);
}
}
关于javascript - 使用嵌套的异步请求循环遍历异步请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54904818/