我正在尝试使服务器并发获取请求,为此,我编写了以下功能。
问题
如果单个呼叫失败,那么我将无法获得其余请求的响应。
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)
});
})
}
能否获得所有请求的结果,无论请求失败还是成功?
答案 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);
}
);