如何发送多个API请求?所以我下面有这段代码
const productID= [12, 43, 65, 87, 45, 76, 87];
productID.map(id => {
API.removeItem(id, (err, response) => {
if (response.status === 'success') {
console.log('remove a product');
}else {
console.log(err);
}
})
})
问题在于它不等待第一个API请求完成并返回响应,而仅删除一个项目。所以基本上我希望它变得同步,这就是为什么我使用async等待来解决我的问题的原因。
async function removeProducts() {
const productID = [12, 43, 65, 87, 45, 76, 87];
const result = await Promise.all(productID.map(id => {
API.removeItem(id, (err, response) => {
if (response.status === 'success') {
console.log('remove a product');
}else {
console.log(err);
}
});
}));
}
此操作的结果与第一个代码段几乎相同,但是这次它能够删除2个产品项。我希望仅在上一个请求完成时才发出下一个请求。我该怎么办?
答案 0 :(得分:1)
您第二次尝试的问题是Promise.all()
将一个promises数组作为参数。 Promise.all()
函数还返回一个诺言本身,当传入的数组中的每个诺言都得到解析时,它就会被解析。
array.map
不返回promise,它返回一个新数组,其中包含使用提供的函数调用的数组中每个项目的结果。详细了解地图功能here。
相反,为返回承诺的API调用创建包装函数。
const productID = [12, 43, 65, 87, 45, 76, 87];
let removeProductID = (id) => {
return new Promise((resolve, reject) => {
API.removeItem(id, (err, response) => {
if (response.status === 'success') {
console.log('remove a product');
resolve(response);
} else {
console.log(err);
reject(err);
}
})
});
}
let removeAllProductIDs = async () => {
for(let id of productID) {
await removeProductID(id);
}
}
removeAllProductIDs();
答案 1 :(得分:0)
实际上 Promise.All()发出并行请求,因此这不是您要查找的解决方案。
您需要的是收益,然后再次提出请求,依此类推。为此,您需要 API.removeItem 返回 Promise 。如果不是,则可以使用Promise API包装此函数以返回Promise。
async function removeItem(id) {
return new Promise((resolve, reject) => {
API.removeItem(id, (err, response) => {
if (response.status === 'success') {
resolve("message or data"); // or pass id or anything
} else {
console.log(err);
reject(err)
}
})
})
}
现在您可以使用此功能产生结果。
const productID = [12, 43, 65, 87, 45, 76, 87];
async function removeProducts() {
for (let i = 0; i < productID.length; i++) {
const result = await removeItem(productID[i]); // will return resolved value here
// sequence
}
}
答案 2 :(得分:0)
const productID = [12, 43, 65, 87, 45, 76, 87];
function process() {
if (productID.length == 0) return;
var id = productID.pop();
API.removeItem(id, (err, response) => {
if (response.status === 'success') {
console.log('remove a product');
process(); // process next item if success
} else {
console.log(err);
}
});
};
process();
答案 3 :(得分:0)
与其他答案类似,首先声明API.removeItem
(如果您的环境是Node.js,则可以使用util.promisify
,否则请使用Promise
构造函数,如其他答案所示):
const {promisify} = require('util');
const removeItem = promisify(API.removeItem);
然后,如果您不介意引入第三方模块,则可以使用async-af
使用async forEach(我维护的模块)依次遍历ID:
const AsyncAF = require('async-af');
const removeItems = ids => AsyncAF(ids).series.forEach(removeItem);
removeItems([12, 43, 65, 87, 45, 76, 87]);
或者,您可以使用Vanilla JS顺序遍历id。例如,这是使用Array.prototype.reduce
的实现:
const removeItems = ids => ids.reduce((acc, id) => (
acc.then(() => removeItem(id))
), Promise.resolve());
removeItems([12, 43, 65, 87, 45, 76, 87]);