【问题标题】:AXIOS: how to run http requests concurrently and get the result of all requests event if a request failsAXIOS:如何同时运行http请求并在请求失败时获取所有请求事件的结果
【发布时间】:2019-04-03 11:54:41
【问题描述】:

我正在尝试让服务器同时获取请求,为此我编写了以下函数。

问题

如果单个呼叫失败,那么我无法获得其余请求的响应。

export const getAll = async (collection) => {
    return new Promise((resolve, reject) => {
        const requests = collection.map(req => {
            const config = {
                headers: req.headers,
                params: req.params
            }
            return axios.get(req.url, config);
        })

        axios.all(requests)
            .then(axios.spread((...args) => {
                // all succerss
                resolve(args);
            }))
            .catch(function (error) {
                // single call fails and all calls are lost
                reject(error)
            });
    })
}

无论失败还是成功,是否可以获得所有请求的结果?

【问题讨论】:

    标签: javascript reactjs promise axios


    【解决方案1】:

    换句话说,即使请求失败,您也希望像请求成功一样执行其余代码。

    假设响应不能是null。然后我们捕获请求的错误并在这种情况下返回 null 用于请求。

    export const getAll = async (collection) => {
        const requests = collection.map(req => {
            const config = {
                headers: req.headers,
                params: req.params
            };
            return axios.get(req.url, config).catch(() => null);
        })
        return axios.all(requests);
    }
    

    所以如果你有 catch() 并且它没有抛出异常,那么所有以后的代码都会像 Promise 一样被解决而不是被拒绝。

    还请注意,您不需要从 async 函数显式返回 Promise,因为它会自动发生。更重要的是:由于函数内部没有await,因此实际上不需要将其标记为async。最后axios.all 返回Promise 所以你不需要手动resolve/reject Promise。

    【讨论】:

    • 它就像一个魅力。非常感谢您的回答
    • 这是我见过的最优雅的方式。很漂亮。
    • 非常好,虽然他们计划删除它,所以最好使用Promise.all 而不是axios.all github.com/axios/axios/issues/1042
    【解决方案2】:

    我过去这样做的方法是将我的 promise 的返回值包装到一个具有 result 字段或类似字段和 err 字段的对象中:

    export const getAll = async (collection) => {
        const requests = collection.map(req => {
            const config = {
                headers: req.headers,
                params: req.params
            }
    
            return axios.get(req.url, config)
                //wrap all responses into objects and always resolve
                .then(
                    (response) => ({ response }),
                    (err) => ({ err })
                );
        });
    
        return axios.all(requests)
            //note that .then(axios.spread((...args) => {}) is the same as not using
            //spread at all: .then((args) => {})
            .then(axios.spread((...args) => {
                //getAll will resolve with a value of
                //[{ response: {}, err: null }, ...]
    
                return args;
            }))
            .catch((err) => {
                //this won't be executed unless there's an error in your axios.all
                //.then block
    
                throw err;
            });
    }
    

    另请参阅 @skyboyer 的帖子,了解他对您的其余代码提出的一些要点。

    【讨论】:

      【解决方案3】:

      这是基于 Andrew 解决方案的完整的基于节点 js 的示例:

      const axios = require('axios');
      
      const getAll = async (collection) => {
          const requests = collection.map(req => {
              const config = {
                  // headers: req.headers,
                  params: req.params
              }
      
              return axios.get(req.url, config)
              //wrap all responses into objects and always resolve
                  .then(
                      (apiResponse) => ({
                          apiResponse
                      }),
                      (apiError) => ({
                          apiError
                      })
                  );
          });
      
          return axios.all(requests)
          //note that .then(axios.spread((...args) => {}) is the same as not using
          //spread at all: .then((args) => {})
              .then(axios.spread((...args) => {
                  //getAll will resolve with a value of
                  //[{ response: {}, err: null }, ...]
      
                  return args;
              }))
              .catch((axiosError) => {
                  //this won't be executed unless there's an error in your axios.all
                  //.then block
      
                  throw axiosError;
              });
      }
      
      let api1 = {url: "http://localhost:3000/test?id=1001", param: ""};
      let api2 = {url: "http://localhost:3000/test?id=1002", param: ""};
      let api3 = {url: "http://localhost:3000/test?id=1003", param: ""};
      let apis = [api1, api2, api3];
      
      getAll(apis).then((res) => {
              console.log("getAll call finished");
              //console.log(res);
          }
      );
      

      【讨论】:

        猜你喜欢
        • 2018-04-19
        • 2016-11-10
        • 2020-11-26
        • 2020-03-29
        • 2021-10-03
        • 2017-05-18
        • 2020-11-26
        • 1970-01-01
        • 2019-02-25
        相关资源
        最近更新 更多