[英]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.