I think the hardest part of implementing promises is the chain call. Here’s an example of a Promise chain call:

(new Promise(resolve= > {
  resolve(1)
})).then(data= > {
  console.log(data)
  return new Promise(
    resolve= > setTimeout(() = > resolve(2), 100)
  )
}).then(data= > {
  console.log(data)
  return Promise.resolve(3)
}).then(data= > console.log(data))
Copy the code

The code above prints: 1,2,3. A chain call is an asynchronous operation performed sequentially, passing the data returned from the then of the previous Promise to the next Promise. Before we move on, you can try implementing the Promise chain call yourself.

implementation

1 supports non-chained invocation

Let’s first implement a non-chained call to MyPromise that satisfies the following call:

// Case 1: output 1.
(new MyPromise(resolve= > {
  resolve(1)
})).then(data= > console.log(data));

// Case 2: output 2.
(new MyPromise(resolve= > {
   setTimeout(() = > resolve(2), 100)
})).then(data= > console.log(data))
Copy the code

The implementation code is as follows:

const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'

class MyPromise {
  constructor(fn) {
    this.status = PENDING
    this.data = null
    fn(this._resolve.bind(this))}_resolve(data) {
    if (this.status === PENDING) {
      this.status = FULFILLED
      this.data = data
      this.callback && this.callback(data)
    }
  }

  then(fulfilledCallback) {
    switch (this.status) {
      case PENDING:  // For case 1
        this.callback = fulfilledCallback
        break;
      case FULFILLED: // For case 2
        fulfilledCallback(this.data)
        break; }}}Copy the code

2 supports chained invocation

Satisfy the following call:

// outputs: 1,2,3
(new MyPromise(resolve= > {
  resolve(1)
})).then((data) = > {
  console.log(data)
  return new MyPromise(
    resolve= > setTimeout(() = > resolve(2), 100)
  )
}).then((data) = > {
  console.log(data)
  return 
}).then((data) = > {
  console.log(data)
})
Copy the code

To support chained calls, then should also return a MyPromise object. And the returned MyPromise object is attached to another MyPromise object in the callback. We just rewrite the then function. The code implementation is as follows:

then(fulfilledCallback) {
  return new MyPromise((resolve, reject) = > {
    const fulfilled = () = > {
    const res = fulfilledCallback(this.data)
      return this.resolvePromise(res, resolve, reject)
    }

    switch (this.status) {
      case PENDING:
        this.callback = fulfilled
        break;
      case FULFILLED:
        fulfilled()
        break; }})}resolvePromise(fulfillRes, resolve, reject) {
  if(fulfillRes instanceof MyPromise) {
    // Pass resolve's data down
    fulfillRes.then(resolve, reject)
  } else {
    resolve(fulfillRes)
  }
}
Copy the code

At this point, the chain call of Promise is implemented. The complete code is as follows:

const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
class MyPromise {
  constructor(fn) {
    this.status = PENDING
    this.data = null
    fn(this._resolve.bind(this))}_resolve(data) {
    if (this.status === PENDING) {
      this.status = FULFILLED
      this.data = data
      this.callback && this.callback(data)
    }
  }

  then(fulfilledCallback) {
    return new MyPromise((resolve, reject) = > {
      const fulfilled = () = > {
        const res = fulfilledCallback(this.data)
        return this.resolvePromise(res, resolve, reject)
      }

      switch (this.status) {
        case PENDING:
          this.callback = fulfilled
          break;
        case FULFILLED:
          fulfilled()
          break; }})}// Implement chain core code
  resolvePromise(fulfillRes, resolve, reject) {
    if(fulfillRes instanceof MyPromise) {
      // Pass resolve's data down
      fulfillRes.then(resolve, reject)
    } else {
      resolve(fulfillRes)
    }
  }
}
Copy the code

Recommended reading

“Starting with a Promise interview question that keeps me up at night, an in-depth analysis of the Promise implementation details” : juejin.cn/post/694531… . The article details the implementation of Promise.