In ES6, Promise is an improvement of traditional callback. We always put the async request in new Promise(), it will wait until you get the result for resolve or reject. While if you put the async function in then(), whatever you return in that async request, then() will return Promise.resolve(undefined) as async callback is just local function.

  new Promise((resolve, reject) => {
    reject('No');
  }).then(e =>{ // reject jump this step
    console.log(`1 then ${e}`);
  }).catch(e => { // e == 'No'
    console.log(`2 catch ${e}`);
    // 2 catch No, return Promise.resolve(undefined)
  }).then(e => { // e == 'undefined'
    console.log(`3 then ${e}`); // 3 then undefined
    return Promise.resolve('what?');
  }).catch(e => { // resolve jump this step
    console.log(`4 catch ${e}`);
  }).then(e => { // e == 'what'
    console.log(`5 then ${e}`); // 5 then what?
  })

If you want to pass the parameters, return in the end line of then function. They will be wrapped as Promise.resolve(your parameters), regardless of basic type or Object.

When catch() does not return Promise.reject(...), it will return Promise.resolve(undefined). All the errors thrown halfway can be centralized processed in the final catch().

There is an interesting test online:

  doSomething().then(function () {
    return doSomethingElse();
    // Promise.resolve(what doSomethingElse returns)
  });

  doSomething().then(function () {
    doSomethingElse();
    // Promise.resolve(undefined)
  });

  doSomething().then(
    doSomethingElse()
    // this step will be ignored
    // as then should contain a function definition
  );

  doSomething().then(
    doSomethingElse
    // Promise.resolve(what doSomethingElse returns)
    // equals the first example
  );