简体   繁体   中英

Promise.all causes Jest to display UnhandledPromiseRejectionWarning

I have some code which calls Promise.all. It runs OK in the browser with no warnings in the console.

There are 3 functions f1, f2 & f3 all of which return a promise. The code looks like this

Promise.all([
  f1(),
  f2(),
  f3()
]).then((values) => {
  resolve({success: true})
}).catch(err => {
  reject(err)
})

When I use Jest to test the file containing the above code I see this error.

(node:17177) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 18)

Is this the wrong way to code the above or is it a bug within Jest?

Here's the actual code that I'm using:

getDataFromDatabase() {
  return new Promise((resolve, reject) => {
    const assessmentUrl = `${this.assessmentUrl}`
    http.get(assessmentUrl).then(response => {
      if (response.data.record === null) {
        Promise.all([
          this._getPupilPlacement(),
          this._getSurveyQuestions(),
          this._getCompetencies()
        ]).then((values) => {
          successState.pupilPlacement = values[0].pupilPlacement
          successState.items = values[1].items
          successState.formid = values[2].formid
          successState.competencies = values[3].competencies
          const panels = this.getPanels(values[3].competencies)
          successState.panels = panels
          successState.numPages = panels.length
          successState.itemsAreOverridden = true
          resolve(successState)
        }).catch(err => {
          reject(err)
        })

      }
      else {
        resolve(response.data.record)
      }
    })
  })
}

Avoid the Promise constructor antipattern ! You were forgetting to handle errors from the http.get(assessmentUrl) promise.

You should be writing

getDataFromDatabase() {
  const assessmentUrl = `${this.assessmentUrl}`
  return http.get(assessmentUrl).then(response => {
//^^^^^^
    if (response.data.record !== null)
      return response.data.record;
    return Promise.all([
//  ^^^^^^
      this._getPupilPlacement(),
      this._getSurveyQuestions(),
      this._getCompetencies()
    ]).then(values => {
      const panels = this.getPanels(values[3].competencies)
      return {
//    ^^^^^^
        pupilPlacement: values[0].pupilPlacement,
        items: values[1].items,
        formid: values[2].formid,
        competencies: values[3].competencies,
        panels: panels,
        numPages: panels.length,
        itemsAreOverridden: true,
      };
    });
  });
}

Explanation:

Calling reject will throw an error. If your top level promise doesn't catch it, then well it's an unhandled promise.

承诺图片说明 MDN Image src

Solution:

getDataFromDatabase().catch(err=>console.lor(err.message));

Example of a promise that rejects.:

 function getDataFromDatabase(){ return Promise.reject(123); } getDataFromDatabase() .then(data=>console.log("Success " + data)) .catch(err=>console.log("Error " + err)); 

Promise MDN doc

Future recommendation:

For every child promise you seem to be adding a .catch() which isn't needed. As long as somewhere higher up there is a catch , then the promise will be handled.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM