Reactjs promise.all order of calls

2019-08-19 08:18发布

问题:

I'm trying to fetch the studentDataPromise before fetchLoansPromise since it depends on the data studentDataPromise returns.

This is my current code:

Promise.all([studentDataPromise, fetchclassesPromise, fetchLoansPromise])
        .then(() => {
            toggleIsReady();
        })
        .catch(error => {
            throw new Error(error);
        });

This is the current order of events:

  1. toggleIsReady initially set to false, but is now true.
  2. fetchLoansPromise - can’t fetch it doesn’t have the studentDataPromise fetched
  3. studentDataPromise- fetches it correctly
  4. toggleIsReady - Is now set to false
  5. fetchclassesPromise - fetches it correctly

Any suggestions?

回答1:

Promise.all() gets executed when all the promises you pass in resolve. That means you don't have guarantee that your studentDataPromise gets resolved before fetchLoanPromise. I recommend having a glance here Promise.all

The easy way around it would be to use .then() once the promise resolves. This could look like so:

let studentDataPromise = new Promise((resolve, reject) => {
  /**
   * 
   * 
   * **/
   reject(/**Something goes here**/)

  /**
   * Some Code here
   * 
   */
  resolve(/**Something goes here**/)

})

studentDataPromise
  .then((/**Whatever you return from resolve()**/) => {
    // Here you can call your fetchLoansPromise
    fetchLoansPromise
      .then(() => {
        /*** ***/
      })
  })

Or even more eleganty, with using async/await:

let studentDataPromise = () => {
  return new Promise((resolve, reject) => {

    /**
     * 
     * **/

     resolve()

  })
}


let someAsyncFunction = async () => {
  try {
    let studentData = await studentDataPromise()
    // Here you are guaranteed that your promise resolved
    // And you can call your other function
  }
  catch (err) {
  }
}

In either way you have to make sure that your first promise resolves, then you can your other functions. Promise.all() is great when you want to make sure that something happens after all your promises (which you pass on) get resolved. Hope this helps



回答2:

Call studentDataPromise before other promisses.

studentDataPromise().then((data) => {
  Promise.all([fetchclassesPromise, fetchLoansPromise])
})


回答3:

You could do something like

Promise.all([studentDataPromise, fetchclassesPromise])
    .then(([studentData, classesData]) => fetchLoans(studentData))
    .then(() => toggleIsReady())
    .catch(error => {
        // handle exception
    });

Or using async await:

try {
    const [studentData, classesData] = await Promise.all([studentDataPromise, fetchclassesPromise]);
    const loansData = await fetchLoans(studentData);
    toggleIsRead();
} catch (e) {
    // handle exception
}

Where fetchLoans would return a fetchLoansPromise.



回答4:

This is how I solved it, Now 'fetchStudentData' is resolved before 'fetchLoansPromise'.

    let studentDataPromise = null;
    let fetchClassesPromise = null;
    let fetchLoansPromise = null;
    useEffect(() => {
        studentDataPromise = fetchStudentData();
    }, []);

    useEffect(() => {
        fetchClassesPromise = fetchClasses();
    }, []);

    useEffect(() => {
        fetchLoansPromise = resolveStudentDataPromise();
    }, []);
    async function resolveStudentDataPromise() {
        await Promise.all([studentDataPromise]);
        fetchLoans();
    }

    Promise.all([studentDataPromise, fetchClassesPromise, fetchLoansPromise])
        .then(() => {
            toggleIsReady();
        })
        .catch(error => {
            throw new Error(error);
        });

Thank you everyone