Have nothing to do, want to interview a series of questions, first to a classic handwritten Promise, will you? I can’t, so I’ll write a…

1. Promise explanation

If you want to implement a Promise by hand, you need to know the principle of the Promise and its internal process. It is important to know what to write, just like writing business split pages and dismantling components. Promise, as we know it, is an asynchronous object. You can pass a resolve, reject function as follows:

const pro = new Promise((res, rej) = > {
  console.log('The promise is fulfilled.')})Copy the code

This is a big pity, which is a pity. Once the state of a Promise object changes, it will not change back again. This is actually a guarantee for our subsequent calls to the function. (PS: The code in the Promise object is executed synchronously)

Promise.then () : gets the normal result of the asynchronous task, promise.catch() : gets the abnormal result of the asynchronous task, promise.finaly() : the asynchronous task will execute whether it succeeds or not.

const pro = new Promise((res, rej) = > {
  console.log('The promise is fulfilled.')
  res('success')
  // rej(' failed ')
})
pro
  .then(res= > {
    console.log(res)
  })
  .catch(rej= > {
    console.log(rej)
  })
  .finally(() = > {
    console.log('complete')})Copy the code

An important chained invocation of promises is that each Promise returns a Promise object that can be used to execute subsequent state method calls. If the logic needs to break, you can interrupt the chain call manually by throwing a throw error where the interrupt is needed.

There are also two methods used, promise.all (): multiple asynchronous tasks are processed concurrently, and all tasks are successfully executed before the result is obtained. Promise.race (): multiple asynchronous tasks are processed concurrently, and as long as one task is successfully executed, the result is obtained

The above is the content of the Promise, can also be said to be the function point separation, the following is our own handwriting a Promise link.

2. Write a Promise

  • First, we write a myPromise class that implements a function argument and executes it as soon as it is passed
class myPromise{
  constructor(immediate) {
    / / success
    let resolve = () = > {}
    / / fail
    let reject = () = > {}
    // Execute the function immediately
    immediate()
  }
}
Copy the code
  • Then define the three states in myPromise: pengding, depressing, and rejected
class myPromise {
  constructor(immediate) {
    this.state = 'pending'
    this.value // The value on success
    this.error // Failure value
    / / success
    let resolve = (res) = > {
      if (this.state === 'pending') {
        this.state = 'fufilled'
        this.value = res
      }
    }
    / / fail
    let reject = (rej) = > {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.error = rej
      }
    }
    // Execute the function immediately
    immediate(resolve, reject)
  }
}

new myPromise((resolve, reject) = > {
  resolve('It worked')})// console output Promise {state: "fufilled", value: "successful "}
Copy the code
  • Next, implement the.then method
class myPromise {
  constructor(immediate) {
    this.state = 'pending'
    this.value // The value on success
    this.error // Failure value
    / / success
    let resolve = (res) = > {
      if (this.state === 'pending') {
        this.state = 'fufilled'
        this.value = res
      }
    }
    / / fail
    let reject = (rej) = > {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.error = rej
      }
    }
    // Execute the function immediately
    immediate(resolve, reject)
  }

  // Declare the then method
  then (fufilledCall, rejectedCall) {
    if (this.state === 'fufilled') {
      fufilledCall(this.value)
    }
    if (this.state === 'rejected') {
      rejectedCall(this.error)
    }
  }
}

new myPromise((resolve, reject) = > {
  resolve('It worked')
})
  .then(res= > {
    console.log('Successful callback', res)
  })
// Console output success callback success
Copy the code
  • Then implement. Then chain call (complete code)
class myPromise {
  constructor(immediate) {
    this.state = 'pending'
    this.value // The value on success
    this.error // Failure value
    / / success
    let resolve = (res) = > {
      if (this.state === 'pending') {
        this.state = 'fufilled'
        this.value = res
      }
    }
    / / fail
    let reject = (rej) = > {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.error = rej
      }
    }
    // Execute the function immediately
    immediate(resolve, reject)
  }

  // Declare the then method
  then (fufilledCall, rejectedCall) {
    let promise2
    promise2 = new myPromise((resolve, reject) = > {
      if (this.state === 'fufilled') {
        let x = fufilledCall(this.value);
        resolvePromise(promise2, x, resolve, reject)
      }
      if (this.state === 'rejected') {
        let x = rejectedCall(this.error);
        resolvePromise(promise2, x, resolve, reject)
      }
    })
    return promise2
  }
}

/** * Function that handles promise recursion ** promise2 {promise} default return promise * x {*} our own return object * resolve * reject */
function resolvePromise (promise2, x, resolve, reject) {

  // Loop reference error
  if (x === promise2) {
    // reject error throw
    return reject(new TypeError('Chaining cycle detected for promise'));
  }

  // Lock to prevent multiple calls
  let called;

  // x is not null and x is an object or function
  if(x ! =null && (typeof x === 'object' || typeof x === 'function')) {
    try {
      // A+ specifies the then method that declares then = x
      let then = x.then;
      // If then is a function, the default is Promise
      if (typeof then === 'function') {
        // then executes the first argument this, followed by a successful callback and a failed callback
        then.call(x, y= > {
          // Only one can be called for success or failure
          if (called) return;
          called = true;
          // Core point 2: the result of resolve is still a promise
          resolvePromise(promise2, y, resolve, reject);
        }, err= > {
          // Only one can be called for success or failure
          if (called) return;
          called = true;
          reject(err);// If you fail, you fail})}else {
        resolve(x); // You can do just that}}catch (e) { // Go to catch is also a failure
      if (called) return;
      called = true;
      // Then is not validreject(e); }}else{ resolve(x); }}new myPromise((resolve, reject) = > {
  resolve('It worked')
})
  .then(res= > {
    console.log('Successful callback', res)
    return new myPromise((resolve, reject) = > {
      resolve('hello world');
    })
  })
  .then(res= > {
    console.log('Successful callback 2', res)
    return new myPromise((resolve, reject) = > {
      resolve('haha')
    })
  })
  .then(res= > {
    console.log('Successful callback 3', res)
  })
Copy the code

This is basically complete with a handwritten Promise, but every time you need to manually return an object in the.then, it’s not perfect. I haven’t thought of a good solution yet. There are good methods can also send out, let me learn.