Returning an Axios Promise from function

2019-02-01 21:34发布

问题:

Can someone please explain why returning an Axios promise allows for further chaining, but returning after applying a then()/catch() method does not?

Example:

const url = 'https://58f58f38c9deb71200ceece2.mockapi.io/Mapss'
    
function createRequest1() {
  const request = axios.get(url)

  request
  .then(result => console.log('(1) Inside result:', result))
  .catch(error => console.error('(1) Inside error:', error))

  return request
}

function createRequest2() {
  const request = axios.get(url)

  return request
  .then(result => console.log('(2) Inside result:', result))
  .catch(error => console.error('(2) Inside error:', error))
}

createRequest1()
.then(result => console.log('(1) Outside result:', result))
.catch(error => console.error('(1) Outside error:', error))

createRequest2()
.then(result => console.log('(2) Outside result:', result))
.catch(error => console.error('(2) Outside error:', error))
<script src="https://unpkg.com/axios@0.16.1/dist/axios.min.js"></script>

https://jsfiddle.net/nandastone/81zdvodv/1/

I understand that Promise methods should return a value to be chained, but why is there a difference between these two return methods?

回答1:

Your first example returns the original promise. Your second example returns a different promise, the one created by calling catch.

The critical differences between the two are:

  1. In your second example, you're not passing on the resolution value, so the promise returned by your then is resolved with undefined (the return value of console.log).

  2. In your second example, you're converting rejections into resolutions with undefined (by returning the result of console.log out of catch). A catch handler that doesn't throw or return a promise that's rejected converts a rejection into a resolution.

One of the key things about promise chains is that they transform the result; every call to then or catch creates a new promise, and their handlers can modify what's sent downstream as the result passes through them.

The usual pattern would indeed be to return the result of the chain, but for the functions in the chain to either intentionally transform the result or pass it on. Normally, you wouldn't have a catch handler except at the terminal end of the chain, unless you're using it to correct the error condition (intentionally converting a rejection into a resolution).

If you wanted to just log what passed through while still allowing callers to see it but did want to return the result of the chain for whatever reason, you'd do this:

return request
    .then(result => { console.log(result); return result; })
    .catch(error => { console.error(error); return Promise.reject(error); });

or using throw:

return request
    .then(result => { console.log(result); return result; })
    .catch(error => { console.error(error); throw error; });