如何在React中执行下一个功能之前完成所有提取? [英] How to finish all fetch before executing next function in React?
问题描述
使用ReactJS,我尝试获取和重构两个不同的API点:students
和scores
.它们都是对象数组.
Using ReactJS, I have two different API points that I am trying to get and restructure: students
and scores
. They are both an array of objects.
我的目标是:首先,获取学生和分数,然后,将学生和分数保存在状态中,我将对其进行修改,并根据学生和分数状态创建一个新状态.简而言之,我有3个功能:getStudents
,getScores
和rearrangeStudentsAndScores
. getStudents
和getScores
需要先完成,然后才能运行rearrangeStudentsAndScores
.
My goal is : first, get students and scores, and second, with students and scores saved in state, I will modify them and create a new state based on students and scores state. In short, I have 3 functions: getStudents
, getScores
, and rearrangeStudentsAndScores
. getStudents
and getScores
need to finish before rearrangeStudentsAndScores
can run.
我的问题是:有时rearrangeStudentsAndScores
将在getScores
完成之前运行. rearrangeStudentsAndScores
搞砸了.但是有时它会完成.不知道为什么它在50%的时间内都能正常工作,但是我需要使其在100%的时间内都能正常工作.
My problem is: sometimes rearrangeStudentsAndScores
will run before getScores
would complete. That messed rearrangeStudentsAndScores
up. But sometimes it would complete. Not sure why it works 50% of the time, but I need to make it work 100% of the time.
这是我在Client
文件中fetch
students and scores
所要执行的操作:
This is what I have to fetch
students and scores
in my Client
file:
function getStudents(cb){
return fetch(`api/students`, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}).then((response) => response.json())
.then(cb)
};
function getScores(cb){
return fetch(`api/scores`, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}).then((response) => response.json())
.then(cb)
};
然后我将它们组合在一起:
I then combined them together:
function getStudentsAndScores(cbStudent, cbScores, cbStudentsScores){
getStudents(cbStudent).then(getScores(cbScores)).then(cbStudentsScores);
}
在我的React应用中,我有以下内容:
In my react app, I have the following:
getStudentsAndScores(){
Client.getStudentsAndScores(
(students) => {this.setState({students})},
(scores) => {this.setState({scores})},
this.rearrangeStudentsWithScores
)
}
rearrangeStudentsWithScores(){
console.log('hello rearrange!')
console.log('students:')
console.log(this.state.students);
console.log('scores:');
console.log(this.state.scores); //this returns [] half of the time
if (this.state.students.length > 0){
const studentsScores = {};
const students = this.state.students;
const scores = this.state.scores;
...
}
}
以某种方式,到我到达rearrangeStudentsWithScores
时,this.state.scores
仍将是[]
.
Somehow, by the time I get to rearrangeStudentsWithScores
, this.state.scores
will still be []
.
如何在运行rearrangeStudentsWithScores
之前确保同时加载this.state.students
和this.state.scores
?
How can I ensure that this.state.students
and this.state.scores
are both loaded before I run rearrangeStudentsWithScores
?
推荐答案
您的代码混合了继续回调和承诺.您会发现使用一种异步流控制方法更容易对此进行推理.让我们使用Promises,因为fetch
使用它们.
Your code mixes continuation callbacks and Promises. You'll find it easier to reason about it you use one approach for async flow control. Let's use Promises, because fetch
uses them.
// Refactor getStudents and getScores to return Promise for their response bodies
function getStudents(){
return fetch(`api/students`, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}).then((response) => response.json())
};
function getScores(){
return fetch(`api/scores`, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}).then((response) => response.json())
};
// Request both students and scores in parallel and return a Promise for both values.
// `Promise.all` returns a new Promise that resolves when all of its arguments resolve.
function getStudentsAndScores(){
return Promise.all([getStudents(), getScores()])
}
// When this Promise resolves, both values will be available.
getStudentsAndScores()
.then(([students, scores]) => {
// both have loaded!
console.log(students, scores);
})
这种方法不仅简单,而且效率更高,因为它可以同时发出两个请求.您的方法一直等到学生被拿到,然后才拿到分数.
As well as being simpler, this approach is more efficient because it makes both requests at the same time; your approach waited until the students were fetched before fetching the scores.
请参阅MDN上的 Promise.all
See Promise.all
on MDN
这篇关于如何在React中执行下一个功能之前完成所有提取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!