Promise is pretty familiar, considering just a few apis, but do you really know Promise? See how many of the 10 questions you can answer correctly, based on some Promise points.

The following promises refer to promise instances in node.js.

Subject to a

const promise = new Promise((resolve, reject) => {
  console.log(1)
  resolve()
  console.log(2)
})
promise.then(() => {
  console.log(3)
})
console.log(4)Copy the code

Running results:

1 2 3 4Copy the code

Explanation: The Promise constructor is executed synchronously, while the functions in promise.then are executed asynchronously.

Topic 2

const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('success') }, 1000) }) const promise2 = promise1.then(() => { throw new Error('error!!! ') }) console.log('promise1', promise1) console.log('promise2', promise2) setTimeout(() => { console.log('promise1', promise1) console.log('promise2', promise2) }, 2000)Copy the code

Running results:

promise1 Promise { <pending> } promise2 Promise { <pending> } (node:50928) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: error!!! (node:50928) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. promise1 Promise {  'success' } promise2 Promise { <rejected> Error: error!!! at promise.then (...) at <anonymous> }Copy the code

A promise has three states: Pending, depressing or Rejected. The state change can only be pending-> depressing or pending-> Rejected. Once the state changes, it cannot be changed again. Promise2 above is not promisE1, but a new Promise instance returned.

The title three

const promise = new Promise((resolve, reject) => {
  resolve('success1')
  reject('error')
  resolve('success2')
})

promise
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })Copy the code

Running results:

then: success1Copy the code

The resolve or reject constructor is valid only on the first execution, and multiple calls have no effect, echoing code 2’s conclusion that once a promise state changes, it cannot be changed again.

The title four

Promise.resolve(1)
  .then((res) => {
    console.log(res)
    return 2
  })
  .catch((err) => {
    return 3
  })
  .then((res) => {
    console.log(res)
  })Copy the code

Running results:

1
2Copy the code

Explanation: Promises can be called chained. When we think of chained calls we usually think of a return this implementation, but that’s not how promises are implemented. A promise returns a new promise each time it is called. Then or. Catch, thereby implementing the chained invocation.

Topic five

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('once')
    resolve('success')
  }, 1000)
})

const start = Date.now()
promise.then((res) => {
  console.log(res, Date.now() - start)
})
promise.then((res) => {
  console.log(res, Date.now() - start)
})Copy the code

Running results:

once
success 1005
success 1007Copy the code

Explanation: A promise’s.then or.catch can be called multiple times, but here the Promise constructor is executed only once. Or once the internal state of a promise changes and it has a value, each subsequent call to.then or.catch will get that value directly.

Topic 6

Promise.resolve() .then(() => { return new Error('error!!! ') }) .then((res) => { console.log('then: ', res) }) .catch((err) => { console.log('catch: ', err) })Copy the code

Running results:

then: Error: error!!!
    at Promise.resolve.then (...)
    at ...Copy the code

An error object in a. Then or. Catch does not throw an error, so it will not be caught by a subsequent. Catch.

return Promise.reject(new Error('error!!! ')) throw new Error('error!!! ')Copy the code

Return new Error(‘ Error!!! ‘) because returning any non-Promise value is wrapped as a Promise object. ‘) equivalent to return promise.resolve (new Error(‘ Error!!! ‘)).

Title seven

const promise = Promise.resolve()
  .then(() => {
    return promise
  })
promise.catch(console.error)Copy the code

Running results:

TypeError: Chaining cycle detected for promise #<Promise>
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)
    at Function.Module.runMain (module.js:667:11)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:607:3Copy the code

Explanation: The value returned by. Then or. Catch cannot be the promise itself, otherwise an infinite loop will occur. Similar to:

process.nextTick(function tick () {
  console.log('tick')
  process.nextTick(tick)
})Copy the code

The title eight

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)Copy the code

Running results:

1Copy the code

Explanation:.then or.catch parameters are expected to be functions, and passing non-functions will result in value penetration.

Title nine

Promise.resolve()
  .then(function success (res) {
    throw new Error('error')
  }, function fail1 (e) {
    console.error('fail1: ', e)
  })
  .catch(function fail2 (e) {
    console.error('fail2: ', e)
  })Copy the code

Running results:

fail2: Error: error
    at success (...)
    at ...Copy the code

Explanation:.then can take two arguments, the first being the function that handled success and the second being the function that handled error. .catch is a shorthand for the second argument to.then, but they are used with a caveat: the second error-handling function of.then does not catch the error thrown by the first successful function, while subsequent.catches catch the previous error. Of course the following code can also be used:

Promise.resolve()
  .then(function success1 (res) {
    throw new Error('error')
  }, function fail1 (e) {
    console.error('fail1: ', e)
  })
  .then(function success2 (res) {
  }, function fail2 (e) {
    console.error('fail2: ', e)
  })Copy the code

The title ten

process.nextTick(() => {
  console.log('nextTick')
})
Promise.resolve()
  .then(() => {
    console.log('then')
  })
setImmediate(() => {
  console.log('setImmediate')
})
console.log('end')Copy the code

Running results:

end
nextTick
then
setImmediateCopy the code

Both Process.nexttick and Promise.then are microtasks, while setImmediate is macroTask and is performed during the check phase of the event loop. Microtasks are executed between each phase of the event cycle (MacroTasks), with a MicroTask executed at the beginning of the event cycle.


This article is written by NSWBMW of graphite documents.