One, foreword

As a frequent interview question —- write a Promise that meets the Promise+ specification. At the beginning is meng, completely without train of thought, but read a lot of people’s various articles have their own train of thought.

In fact, after several handwritten promises in line with the standard, many previous doubts about the promise implementation were solved one by one, and I felt suddenly enlightened. In fact, WHAT I said was that when I did the event loop problem, I would be silly when I met the promise. But a closer look at Promise clears up a lot of questions.

Two, about a Promise to have what points to pay attention to, according to others’ articles, summarize (refer to others’ ideas and expand to add some of their own opinions)

    1. When a New Promise is passed, an executor executor executes immediately
    1. Executor accepts two arguments, resolve and Reject
    1. Promise can only go from pending to rejected, or from pending to depressing
    1. Once a promise’s status is confirmed, it doesn’t change
    1. This is a big pity. Promise has then method. Then receives two parameters, which is onFulfilled, and onRejected, which promise fails
    1. If the promise is successful when calling THEN, ondepressing will be performed and the promise value will be passed in as a parameter. If the promise has failed, then execute onRejected and pass in the reason why the promise failed. If the state of the Promise is pending, ondepressing and onRejected functions need to be stored. After the state is determined, the corresponding functions will be executed successively (release and subscribe).
    1. The onFulfilled and onRejected parameters of then can be default
    1. A promise can be then multiple times, and the then method of a promise returns a promise
    1. This is a big pity. If then returns a result, this result will be passed as a parameter to the successful ondepressing of the next THEN.
    1. If an exception is thrown in THEN, it is passed as an argument to the onRejected callback of the next THEN.
    1. If then returns a promise, then you need to wait for that promise, then you need to wait for that promise to complete. If the promise succeeds, then the next THEN succeeds, and if it fails, then the next THEN fails

Three, hand lift promise


const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

function myPromise(excutor) {

  let self = this;
  // A promise should have these five values
  self.status = PENDING;
  self.value = null;
  self.reason = null;
  // It needs to be stored when the state is always PENDING
  self.onFulfilledCallBacks = [];
  self.onRejectedCallBacks = [];


  // excutor resolve, value is the value to be passed
  function resolve(value) {
    // Avoid multiple resolve
    if (self.status === PENDING) {
      self.value = value;
      self.status = FULFILLED;
      self.onFulfilledCallBacks.forEach(fn= >fn()); }}Reject (reject); reject (reject); reject (reject)
  function reject(reson) {
    // Avoid multiple reject
    if (self.status === PENDING) {
      self.reason = reson;
      self.status = REJECTED;
      self.onRejectedCallBacks.forEach(fn= >fn()); }}// Excutor executes immediately
  try {
    excutor(resolve, reject);
  } catch(e) {
    reject(e);
  }

}

myPromise.prototype.then = function (onFulfilled, onRejected) {
  // Because ondepressing, onRejected can default, so at the beginning we should judge whether it is an executable function
  // ondepressing if this is fulfilled by default, a function that returns the parameters will be executed
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value= > value;
  // onRejected Defaults to a function that throws Reason
  onRejected = typeof onRejected === 'function' ? onRejected : reason= > { throw reason };
  // Since the then function is itself a promise, declare a new promise
  let self = this;
  let promise2 = new myPromise((resolve, reject) = > {
    // The execution succeeded
    if (self.status === FULFILLED) {
      // Ondepressing will be implemented asynchronously. Here is the simulation with settimeout. In fact, promise is implemented asynchronously in the V8 engine
      setTimeout(() = > {
        try {
          // x is the return value of ondepressing
          let x = onFulfilled(self.value);
          // Recursively call the next then (chain call)
          resolvePromise(promise2, x, resolve, reject);
        } catch(e) {
          reject(e)
        }
      }, 0);
    }

    // Execute failed state
    if (self.status === REJECTED) {
      setTimeout(() = > {
        try {
          // x is returned by Reject
          let x = onRejected(self.reason);
          // Recursively call the next then (chain call)
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e)
        }
      }, 0);
    }

    // Execute the wait state
    if (self.status === PENDING) {
      // If it is pending, store it first
      self.onFulfilledCallBacks.push(() = > {
        setTimeout(() = > {
          try {
            // x is the return value of ondepressing
            let x = onFulfilled(self.value);
            // Recursively call the next then (chain call)
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e)
          }
        }, 0);
      })

      self.onRejectedCallBacks.push(() = > {
        setTimeout(() = > {
          try {
            // x is returned by Reject
            let x = onRejected(self.reason);
            // Recursively call the next then (chain call)
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e)
          }
        }, 0); })}})return promise2;
}

function resolvePromise(promise2, x, resolve, reject) {
  let self = this;
  // If the call is promise2 itself, then it is a circular call
  if (promise2 === x) {
    return reject(new TypeError('chaining cycle'));
  }
  let called;
  if (typeof x === 'object' && x || typeof x === 'function') {
    ResolvePromise = resolvePromise = resolvePromise = resolvePromise = resolvePromise
    try {
      let then = x.then;
      if (typeof then === 'function') {
        console.log('x as the promise -- -- -- -- -- -')
        then.call(x, y= > {
          // There can only be one final state
          if (called) return;
          called = true;
          // Continue the recursion
          resolvePromise(promise2, y, resolve, reject);
        }, r= > {
          // There can only be one final state
          if (called) return;
          called = true; reject(r); })}else {
        console.log('x is valued if the value is function or x. teng is not function ------')

        // There can only be one final state
        if (called) return;
        called = true; resolve(x); }}catch(e) {
      // There can only be one final state
      if (called) return;
      called = true; reject(e); }}else {
    console.log('x is undefined or an explicit value ------') resolve(x); }}Copy the code

Follow-up supplementary examples.. Understand code examples