AXIOS:如何在请求失败的情况下并发运行http请求并获取所有请求事件的结果

时间:2018-10-30 12:28:47

标签: javascript reactjs promise axios

我正在尝试使服务器并发获取请求,为此,我编写了以下功能。

问题

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

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

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

3 个答案:

答案 0 :(得分:3)

换句话说,即使请求失败,您也想采取其余代码,例如请求成功。

我们假设响应不能为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已被解决一样,不会被拒绝。

还要注意,您不需要从Promise函数显式返回async,因为它会自动发生。甚至更多:由于您在函数中没有await,因此实际上不需要将其标记为async。最后,axios.all返回Promise,因此您不需要手动进行resolve / reject的承诺。

答案 1 :(得分:1)

我过去这样做的方法是将我的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的帖子,以了解他对其余代码的看法。

答案 2 :(得分:0)

这是基于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);
    }
);