Implement A simple Promise according to the Promise A+ specification

The first thing new Promise() gets is an object

class Promise{}module.exports = Promise
Copy the code

The input to a Promise object is a function

There are three requirements for input:

  1. Check that the input of type: Promise must be a function or an error will be reported

  2. Execute the passed function immediately

  3. The function takes two arguments, resolve and reject

class Promise2 {
    resolve(result){}reject(reason){}constructor(fn) {
    if (typeoffn ! = ='function') {
      throw new Error('Promise must accept a function ');
    }
    // The incoming function is immediately called, with the first argument being this.resolve and the second argument being this.reject
    fn.call(this.this.resolve.bind(this), this.reject.bind(this));
  }
Copy the code

The output of a Promise object is an object with a THEN method

So we continue to refine the THEN method

The THEN method has the following requirements:

  1. Accept two arguments, SUCCESS and fail
  2. If two arguments are not passed, or if the type is not a function, no error is reported, but no operation is performed
  3. The same promise can be called multiple times then promise1.then promise1.then
  4. The two arguments to then are called by resolve and reject

To handle cases where there may be multiple calls to then, we use an array callbacks to store the arguments passed in multiple THEN calls, and an array Handle to store the arguments passed in each THEN call

then(succeed? , fail?) {
    let handle = [];
    if (typeof succeed === 'function') {
      handle[0] = succeed;
    }

    if (typeof fail === 'function') {
      handle[1] = fail;
    }

    this.callbacks.push(handle);
  }
Copy the code

Call the first argument of then with Resolve

The resolve function needs to do two things:

  1. Change the state of the Promise and ensure that the resolve function can only be executed once
  2. The first argument to call THEN
  resolve(result) {
    // Ensure that resolve can be called only once. If the state is not 'pending', exit directly
    if (this.state ! = ='pending') {
      return;
    }
    this.state = 'fulfilled';
    setTimeout(() = > {
      this.callbacks.forEach(handle= > {
        if (typeof handle[0= = ='function') {
          handle[0].call(undefined, result); }}); }); }Copy the code

Call the second argument of the THEN with Reject

The Reject function also needs to do two things:

  • Modify the state of the Promise and ensure that the reject function can only be executed once
  • The second argument to call THEN
 reject(reason) {
    // Ensure that reject can only be called once
    if (this.state ! = ='pending') return;
    this.state = 'rejected';
    setTimeout(() = > {
      this.callbacks.forEach(handle= > {
        if (typeof handle[1= = ='function') {
          handle[1].call(undefined, reason); }}); }); }Copy the code

The ultimate Promise is:

class Promise2 {
  state = 'pending';
  callbacks = [];

  resolve(result) {
    // Ensure that resolve can only be called once
    if (this.state ! = ='pending') {
      return;
    }
    this.state = 'fulfilled';
    // The first argument to the asynchronous call then
    setTimeout(() = > {
      this.callbacks.forEach(handle= > {
        if (typeof handle[0= = ='function') {
          handle[0].call(undefined, result); }}); }); }reject(reason) {
    // Ensure that reject can only be called once
    if (this.state ! = ='pending') return;
    this.state = 'rejected';
     // The second argument to the asynchronous call then
    setTimeout(() = > {
      this.callbacks.forEach(handle= > {
        if (typeof handle[1= = ='function') {
          handle[1].call(undefined, reason); }}); }); }constructor(fn) {
    if (typeoffn ! = ='function') {
      throw new Error('Promise must accept a function ');
    }
    // The incoming function is called immediately
    fn.call(this.this.resolve.bind(this), this.reject.bind(this));
  }

  then(succeed? , fail?) {
    let handle = [];
    if (typeof succeed === 'function') {
      handle[0] = succeed;
    }

    if (typeof fail === 'function') {
      handle[1] = fail;
    }

    this.callbacks.push(handle); }}export default Promise2;
Copy the code

Realize the Promise. All

Ideas:

First analyze the input and output

Enter: array, possibly string, number, Promise object

Output: a Promise object

Then analyze the features of Promise.all:

All elements in the array are successful when they are successful

There is a failure, reject immediately

If the results array is the same size as the input array, the result array is successful and the result array is resolved

Conversely, reject an object if it fails

   all(promises){
     
     Return a Promise object
    return new Promise((resolve, reject) = >{
      // In the extreme case, return an empty array
      if(promises.length === 0) {
        resolve([])
      }else {
        let results = []
        for (let i = 0; i < promises.length; i++) {
          promises[i] = promises[i] instanceof Promise? promises[i]: Promise.resolve(promises[i])
          // Use "then" to get the result
          promises[i].then((result) = >{
            results.push(result)
            // Only when both are successful can we resolve together
            if(result.length === promises.length){
              resolve(results)
            }
          },(err) = >{
            reject(err)
          })

        }
      }

    })
  }
Copy the code

Realize the Promise. Race

/**
   * Promise.race
   * @description This will be FULFILLED * as long as a promise object enters the FULFILLED or REJECTED state@param {*} Values take an array of Promise objects as arguments *@returns Return a Promise instance */
  static race(values) {
    return new Promise((resolve, reject) = > {
      values.forEach((promise) = > {
        promise.then(resolve, reject)
      })
    })
  }
Copy the code

Implement promise. reject and promise.resolve

  // By default, a successful promise is generated
  static resolve(value) {
    return new Promise((resolve, reject) = > {
      resolve(value)
    })
  }
  // By default, a promise will fail
  static reject(reason) {
    return new Promise((resolve, reject) = > {
      reject(reason)
    })
  }
Copy the code

Reference:

Github.com/lgwebdream/…