Koa*_*la7 5 javascript promise reactjs react-hooks use-effect
我正在使用 Promise 进行多次调用。
我要获取的 API 端点是:
看代码
export function getTeamsStats(league, team, type) {
return function(dispatch) {
const url = "https://www.api-football.com/demo/v2/statistics";
let dates = ["2019-08-30", "2019-09-30", "2019-10-30"];
const getAllData = (dates, i) => {
return Promise.allSettled(dates.map(x => url + '/' + 357 + '/' + 5 + '/' + x).map(fetchData));
}
const fetchData = (URL) => {
return axios
.get(URL)
.then(res => {
const {
matchsPlayed: { total: teamsTotalMatchsPlayed},
} = res.data.api.statistics.matchs;
const matchsPlayed = teamsTotalMatchsPlayed;
dispatch(receivedTeamsStat(matchsPlayed, type));
})
.catch(e => {
console.log(e);
});
}
getAllData(dates).then(resp=>{console.log(resp)}).catch(e=>{console.log(e)})
}
}
Run Code Online (Sandbox Code Playgroud)
然后在我的组件中,我将这个特定球队(在本例中为圣保罗)从初始日期30-8-2019到30-10-2019 进行的比赛放入一个数组中
const [dataHomeTeam, setDataHomeTeam] = useState([]);
useEffect(() => {
if (!team.matchsPlayed) {
return ;
}
setDataHomeTeam(prev =>
prev.concat([
{
matches: team.matchsPlayed,
}
])
);
},[team.matchsPlayed]);
console.log('Data Array', dataHomeTeam);
Run Code Online (Sandbox Code Playgroud)
问题是,通常在页面的第一次渲染中,我的匹配顺序是正确的,从30-8-2019 到 30-10-2019
查看控制台日志图像
但有时不是,请看这里
所以问题是,我如何确保 Promise 以正确的请求顺序返回给我?
我正在使用Promise.allSettled,多个不相互依赖才能成功完成的异步任务,但顺序并不总是正确的。
这应该通过Promise.all解决,因为如文档中所述
返回值将按照传递的 Promise 顺序排列,而不管完成顺序。
您遇到的问题是,您通过dispatch根据完成情况调用每个承诺来设置您的状态,并且由于承诺可以在任何给定时间完成(例如,第三个请求可以先完成,因为它们是同时发送的),dispatch将被调用和您的状态管理会将其设置为第一响应(这就是您“有时”会出现此类行为的原因,因为这取决于网络哪个先完成)。
这意味着要么您应该更改dispatch接收已完成承诺的数组,要么在完成后dispatch一一调用,如下面的代码所示 - 全部解析并按顺序分派:
export function getTeamsStats(league, team, type) {
return function (dispatch) {
const url = "https://www.api-football.com/demo/v2/statistics";
let dates = ["2019-08-30", "2019-09-30", "2019-10-30"];
const getAllData = (dates, i) => {
return Promise.all(dates.map(x => url + '/' + 357 + '/' + 5 + '/' + x).map(fetchData));
}
const fetchData = (URL) => {
return axios
.get(URL)
.then(res => {
const {
matchsPlayed: { total: teamsTotalMatchsPlayed },
} = res.data.api.statistics.matchs;
return teamsTotalMatchsPlayed;
})
.catch(e => {
console.log(e);
});
}
getAllData(dates).then(resp => {
console.log(resp)
// 'resp' here are all 'teamsTotalMatchsPlayed' in correct order (here I mean order of call, not promise completion)
// so just dispatch them in order
resp.map(matchsPlayed => receivedTeamsStat(matchsPlayed, type));
}).catch(e => {
console.log(e)
})
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我可能犯了一些语法错误,但您明白了。