简体   繁体   English

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

[英]AXIOS: how to run http requests concurrently and get the result of all requests event if a request fails

I am trying to make server get requests concurrently, in order to do that I have written the following function.我试图让服务器同时获取请求,为了做到这一点,我编写了以下函数。

Problem问题

If a single call is failing then I am not able to get the response of rest of the requests.如果单个调用失败,那么我将无法获得其余请求的响应。

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

Is it possible to get the result of all requests whether it fails or success?是否有可能获得所有请求的结果,无论失败还是成功?

In other words even if request fails you want to act rest of the code like request has succeed.换句话说,即使请求失败,您也希望像请求成功一样执行其余代码。

Let's assume that response cannot be null .让我们假设 response 不能为null Then we catch request's error and return null in this case for request.然后我们捕获请求的错误并在这种情况下为请求返回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);
}

So if you have catch() and it does not throw exception all later code works like Promise has been resolved not rejected.因此,如果您有catch()并且它没有抛出异常,则所有后续代码都可以像 Promise 一样工作,而不是被拒绝。

Also note you don't need to return Promise explicitly from async function because it happens automatically.另请注意,您不需要从async函数显式返回Promise ,因为它会自动发生。 Even more: since you don't have await inside the function you actually don't need it to be marked as async .甚至更多:由于您在函数内没有await您实际上不需要将其标记为async And finally axios.all returns Promise so you don't need to resolve / reject Promise manually.最后axios.all返回Promise因此您无需手动resolve / reject Promise。

the way I've done this in the past is by wrapping the return value of my promise into an object that either has a result field or something similar and an err field:我过去这样做的方法是将我的承诺的返回值包装到一个对象中,该对象具有一个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;
        });
}

also see @skyboyer's post for some good points he's made about the rest of your code.另请参阅@skyboyer 的帖子,了解他对您的其余代码提出的一些优点。

Here is the complete node js based example based on the Andrew solution:以下是基于 Andrew 解决方案的完整基于 node 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);
    }
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM