如何在React中执行下一个功能之前完成所有提取? [英] How to finish all fetch before executing next function in React?

查看:126
本文介绍了如何在React中执行下一个功能之前完成所有提取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用ReactJS,我尝试获取和重构两个不同的API点:studentsscores.它们都是对象数组.

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个功能:getStudentsgetScoresrearrangeStudentsAndScores. getStudentsgetScores需要先完成,然后才能运行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.studentsthis.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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆