【问题标题】:Sending multiple API request using Promise使用 Promise 发送多个 API 请求
【发布时间】:2019-08-22 16:50:39
【问题描述】:

如何发送多个 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 await 来解决我的问题。

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); 
        }
        });
    }));
}

这个结果与第一个代码 sn-p 几乎相同,但这次它能够删除 2 个产品项目。我希望仅在前一个请求完成时才发出下一个请求。我该怎么做?

【问题讨论】:

标签: javascript ajax promise async-await


【解决方案1】:

您第二次尝试的问题是Promise.all() 将一组承诺作为参数。 Promise.all() 函数还返回一个 Promise 本身,当传入的数组中的每个 Promise 都被解析时,该 Promise 本身也被解析。

array.map 不返回承诺,它返回一个新数组,其中包含使用提供的函数调用的数组中每个项目的结果。阅读有关地图功能的更多信息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();

【讨论】:

    【解决方案2】:

    实际上 Promise.All() 发出并行请求,所以这不是您正在寻找的解决方案。

    您需要的是 yield 结果然后发出另一个请求,依此类推。为此,您需要 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
              }
         }
    

    【讨论】:

      【解决方案3】:
      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();
      

      【讨论】:

        【解决方案4】:

        与其他答案一样,首先承诺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]);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-10-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-28
          • 1970-01-01
          相关资源
          最近更新 更多