簡體   English   中英

AXIOS:如何並發運行http請求並在請求失敗時獲取所有請求事件的結果

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

我試圖讓服務器同時獲取請求,為了做到這一點,我編寫了以下函數。

問題

如果單個調用失敗,那么我將無法獲得其余請求的響應。

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

是否有可能獲得所有請求的結果,無論失敗還是成功?

換句話說,即使請求失敗,您也希望像請求成功一樣執行其余代碼。

讓我們假設 response 不能為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。

我過去這樣做的方法是將我的承諾的返回值包裝到一個對象中,該對象具有一個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 的帖子,了解他對您的其余代碼提出的一些優點。

以下是基於 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