Simple version of Promise

wang xiao bo 's photo
wang xiao bo
·Dec 11, 2021·

3 min read

Simple version of Promise

Subscribe to my newsletter and never miss my upcoming articles

Let's first build the general framework of the construction function

const PENDING ='pending'
const RESOLVED ='resolved'
const REJECTED ='rejected'

function MyPromise(fn) {
const that = this
that.state = PENDING
that.value = null
that.resolvedCallbacks = []
that.rejectedCallbacks = []
// To be improved resolve and reject functions
// To be perfected to execute the fn function
}
  • First of all, we created three constants to represent the state. Some frequently used values ​​should be managed by constants, which is convenient for development and later maintenance.

  • The constant that is first created inside the function body, because the code may be executed asynchronously to obtain the correct this object

  • The state of Promise should be pending at the beginning

  • The value variable is used to save the value passed in resolve or reject resolvedCallbacks and rejectedCallbacks are used to save the callbacks in then, because the state may still be waiting when the Promise is executed. At this time, the callbacks in then should be saved for use when the state changes.

Next, let’s improve the resolve and reject functions and add them inside the body of the MyPromise function

function resolve(value) {
  if (that.state === PENDING) {
    that.state = RESOLVED
    that.value = value
    that.resolvedCallbacks.map(cb => cb(that.value))
  }
}

function reject(value) {
  if (that.state === PENDING) {
    that.state = REJECTED
    that.value = value
    that.rejectedCallbacks.map(cb => cb(that.value))
  }
}

The codes of these two functions are similar, so they are parsed together

  • First of all, both functions have to determine whether the current state is waiting, because the specification stipulates that only the waiting state can change the state

  • Change the current state to the corresponding state, and assign the passed value to value

  • Traverse the callback array and execute

After completing the above two functions, we should implement how to execute the function passed in the Promise

try {
  fn(resolve, reject)
} catch (e) {
  reject(e)
}
  • The implementation is very simple, execute the passed parameters and pass the previous two functions as parameters

  • It should be noted that an error may be encountered during the execution of the function, the error needs to be caught and the reject function is executed

Finally, let's implement the more complex then function

MyPromise.prototype.then = function(onFulfilled, onRejected) {
  const that = this
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
  onRejected =
    typeof onRejected === 'function'
      ? onRejected
      : r => {
          throw r
        }
  if (that.state === PENDING) {
    that.resolvedCallbacks.push(onFulfilled)
    that.rejectedCallbacks.push(onRejected)
  }
  if (that.state === RESOLVED) {
    onFulfilled(that.value)
  }
  if (that.state === REJECTED) {
    onRejected(that.value)
  }
}

-First determine whether the two parameters are function types, because these two parameters are optional parameters

  • When the parameter is not a function type, a function needs to be created and assigned to the corresponding parameter, and transparent transmission is also realized,

The next step is a series of logic for judging the state. When the state is not a waiting state, the corresponding function is executed. If the state is in the waiting state, push the function in the callback function. For example, the following code will enter the logic of the waiting state

new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 0)
}).then(value => {
  console.log(value)
})
 
Share this