简体   繁体   中英

Returning Promise in JavaScript es6

Let's say I have a file that is importing a function from the api and doing something with the result.

import api from './api'

const getData = () => {
  api.get(url)
    .then(res => console.log(res))
    .catch(err => console.log(err))
}

I've seen two different styles for returning the response so the error bubbles up.

version 1:

get: (url) => {
  return new Promise((resolve, reject) => axios.get(url)
    .then(res => resolve(res))
    .catch(err => reject(err)) )
}

version 2:

get: (url) => {
  return axios.get(url)
    .then(res => {
      if (res.success == 200) {
        return Promise.resolve(res)
      }
      return Promise.reject(res)
    })
}

What are the differences between the two approaches? Is there a preferred/better method for error handling?

In general, two handy rules:

  1. If your starting point is a promise (the return value of axios.get ), then using new Promise is an anti-pattern. then and catch already create new promises.

  2. Propagate errors, don't convert them to resolutions (until, of course, the point at which your handling those errors, usually near the beginning of the call chain).

Based on that, of those two options, you'd use Version 2, not Version 1.

Version 1 is a bit nonsensical: It eats the resolution value and converts errors to resolutions; it will always resolve to undefined . Remember that the result of the chain is the result of the last thing returned (or thrown) in a then or catch handler. Those two handlers don't return or throw anything, so the chain resolves (rather than rejecting) with undefined .

Version 2 does something: It modifies the promise result based on res.success . But it doesn't need Promise.resolve , it should just be:

get: (url) => axios.get(url).then(res => {
  if (res.success == 200) {
    return res;
  }
  return Promise.reject(res); // Or see note below
})

And there's a camp — which I agree with — which says you should always throw an Error object rather than returning Promise.reject , for stack trace info. So:

get: (url) => axios.get(url).then(res => {
  if (res.success == 200) {
    return res;
  }
  throw new Error(res/*...or something else useful here...*/);
})

There is no real difference with the two versions, at the first one, you are creating a redundant Promise .

axios.get , is a function that returns a Promise there is no need to wrap it with another one.

You can warp with additional Promise if you wanna change the promise logic, meaning that if you wanna resolve no matter of what happened in axios promise. Something like that:

get: (url) => {
  return new Promise((resolve, reject) => axios.get(url)
    .then(res => resolve(res))
    .catch(err => resolve(err)) )
}

but, usually it is not the practice.

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