使用Promise发送多个API请求

时间:2019-04-01 13:38:00

标签: javascript ajax promise async-await

如何发送多个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个产品项。我希望仅在上一个请求完成时才发出下一个请求。我该怎么办?

4 个答案:

答案 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]);