1. A promise is a class that, when executed, passes an executor that executes immediately
  2. There is a big promise, which is fulfilled (fulfilled), (failed) and (pending). Pedding ->fulfilled -> Promise is a big promise
  3. The resolve and reject functions update the state
  4. resolve:fulfilled reject: rejected
  5. The then method determines the state, calling the success callback if the state is success, and calling the failure callback if the state is failure. The then method is defined in the stereotype object
  6. Then a successful callback takes one parameter, indicating the value after the success, and then a failed callback takes one parameter, indicating the reason for the failure
  7. The then method can be called. The callback of the later THEN method returns the value of the callback of the previous THEN method

Think about the way Promise is written

  1. Write body logic code, first write a class, then step by step construction
  2. Then consider the asynchronous call to resolve, which is passed in asynchronous code. So save the success and failure functions and determine if they need to be called again asynchronously
  3. When there are multiple THEN calls, we need to consider using arrays
  4. When you have layers of nested then. You need to deal with chain calls to then, how to return the value of that then to the next THEN, and return the promisee object.
  5. So you need to encapsulate the promise and implement the chain call
  6. If a loop calls a promise,
  7. For error handling, try. Catch is used in constructors and in then success callbacks
  8. Promise.all() writes the static file function all() to handle it
  9. Promise.resolve() passes the argument directly and returns whether it is a Promise object or a non-promise object. It’s an object, it returns directly, it’s not an object, it produces an object, it returns wrapped
  10. Primise. Finally () is still executed once regardless of whether the promise execution succeeds or fails. The end result of this promise can be obtained using the then method
  11. Finally () is not a method of a class; it is a method on a prototype object.
  12. Primise.catch() is the method for prototyping objects. If there is no typo for then, catch() needs to be caught
const  PENDING = 'pending'; / / wait for
const  FULFILLED = 'filfull ed'; / / success
const  REJECTED = 'rejected'; / / wait for

class MyPromise {
  constructor(executor){
    // We need this. Because this is inside the class
    try{
     executor(this.resolve,this.reject)
    }catch(e){
      this.reject(e)
    }
  };
  / / Promise
  status = PENDING;
  // // Value after success
  value = undefined;
  // The cause of the failure
  reason = undefined;
  // Successful callback
  successCallback = []
  // Failed callback
  failCallback = []
  resolve = value= >{
    // If the state is not wait, prevent the program from trying to execute
    if(this.status ! == PENDING)return
    // Change the status to success
    this.status = FULFILLED;
    // Save the successful value
    this.value = value
    Shift () removes the first value, gets it, and returns the rest of the array
    while(this.successCallback.length) this.successCallback.shift()()
  }; 
  reject = err= >{
    // If the state is not wait, prevent the program from trying to execute
    if(this.status ! == PENDING)return
     // Change the status to failed
     this.status = REJECTED; 
     // Cause of save failure
     this.reason = err
     Shift () removes the first value, gets it, and returns the rest of the array
     while(this.failCallback.length) this.failCallback.shift()()
  } 
  then(successCallback,failCallback){
    successCallback=  successCallback ? successCallback : value= >value;
    failCallback=  failCallback ? failCallback : reson= >{ throw(reson)};
    let promise2 = new MyPromise((resolve,reject) = >{
      if(this.status === FULFILLED){
        // Promise2 is not available until new MyPromise is executed. We're now in the new MyPromise process
        Use setTimeout to change it to asynchronous code, let all code execute, and then execute the code inside the function.
        setTimeout(() = >{
          try{
            // Determine whether X is a normal function or a Promise object
            // If the value is normal, call resolve directly
            // If it is a primise object, look at the result returned by the Promise object
            // Call resolve or reject based on the result returned by the Promise object
            let x = successCallback(this.value)
            // Determine if promise2 and X are equal, and if they are, they return themselves
            resolvePrimise(promise2 ,x,resolve,reject)
          }catch(e){
            reject(e)
          }
        },0)}else if(this.status === REJECTED){
        // Promise2 is not available until new MyPromise is executed. We're now in the new MyPromise process
        Use setTimeout to change it to asynchronous code, let all code execute, and then execute the code inside the function.
        setTimeout(() = >{
          try{
            // Determine whether X is a normal function or a Promise object
            // If the value is normal, call resolve directly
            // If it is a primise object, look at the result returned by the Promise object
            // Call resolve or reject based on the result returned by the Promise object
            let x = failCallback(this.reason)
            // Determine if promise2 and X are equal, and if they are, they return themselves
            resolvePrimise(promise2 ,x,resolve,reject)
          }catch(e){
            reject(e)
          }
        },0)}else{
        // Wait state
        // Save successful and failed callbacks
        this.successCallback.push(() = >{
          setTimeout(() = >{
            try{
              // Determine whether X is a normal function or a Promise object
              // If the value is normal, call resolve directly
              // If it is a primise object, look at the result returned by the Promise object
              // Call resolve or reject based on the result returned by the Promise object
              let x = successCallback(this.value)
              // Determine if promise2 and X are equal, and if they are, they return themselves
              resolvePrimise(promise2 ,x,resolve,reject)
            }catch(e){
              reject(e)
            }
          },0)})this.failCallback.push(() = >{
          setTimeout(() = >{
            try{
              // Determine whether X is a normal function or a Promise object
              // If the value is normal, call resolve directly
              // If it is a primise object, look at the result returned by the Promise object
              // Call resolve or reject based on the result returned by the Promise object
              let x = failCallback(this.reason)
              // Determine if promise2 and X are equal, and if they are, they return themselves
              resolvePrimise(promise2 ,x,resolve,reject)
            }catch(e){
              reject(e)
            }
          },0)})}})return promise2
  }
  finaally(callback){
    // We can get success or failure by calling then. It can be called in any case, right
    return this.then(value= >{
      return MyPromise.resolve(callback()).then(() = > value)
    },reject= >{
      return MyPromise.resolve(callback()).then(() = >  {throw reject})
    })
  }  
  catch(failCallback){
    return this.then(undefined,failCallback)
  }
  Declare all to be a static method
  static all(array){
    let result = [];
    let index = 0
    return new MyPromise((resolve,reject) = >{
      function addData(key,value){
        result[key] = value;
        index++
        if(index === array.length){
          resolve(result)
        }
      }
      for(let i= 0; i<array.length; i++){let current = array[i];
        if(current instanceof MyPromise){
          / / promise object
          current.then(value= >addData(i,value) ,reson= >{
            reject(reson)
          })
        }else{
          / / common valuesaddData(i,array[i]); }}})}static resolve(val){
    if(val instanceof MyPromise) val
    return new MyPromise(resolve= >resolve(val))
  }
}

// Determine whether it is normal or Mypromisee
function resolvePrimise(promise2,x,resolve,reject){* *if(promise2 === x){
    // Use return to prevent the following code from executing
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}// if x is an instance of Mypromisee,
  if(x instanceof MyPromise){
    //primose
    //x.then(value=>resolve(value),err => reject(err))
    x.then(resolve,reject)
  }else{
    / / common values
    resolve(x) 
  }
   
}
Copy the code

This is the first step in the body code, and everything is adapted from that first step. Combine thinking and Promise writing to pay attention to points

const PENDING = 'peding' const REJECTED = 'rejected' const FILFULLED = 'filfulled' class MyPromise{ Constructor (executor){executor(this.resolve,this.reject)} status = PENDING Value = undefined // Filed = of successful data Resolve = value =>{if(this.status! == PENDING) return this.status = FILFULLED this.value = value } reject = filed =>{ if(this.status ! == PENDING) return this.status = REJECTED this.filed = filed } then(successCallback,failCallback){ if(this.status == FILFULLED){ successCallback(this.value) }else if(this.status == REJECTED){ failCallback(this.filed) } } } let b= new MyPromise((resolve,reject)=>{// resolve(' success ') reject('shibao')}) b.chen (res=>{console.log(res)},err=>{ console.log(err) })Copy the code

The following is the code test area, for reference only, you can achieve their own test methods

Let primise = new MyPromise((resolve,reject)=>{// throw new Error('executor Error') // resolve(' success ') setTimeout(()=>{ Resolve (' success 1')},2000) // resolve(' success 1') // reject(' failure ')}) let primise1 = new MyPromise((resolve,reject)=>{// Resolve (' p3 success ') / / setTimeout (() = > {/ / resolve (' 1 'success) / /}, 2000) reject (' p2 failure')}) / / a.t hen ((resolve) = > {/ / console.log(resolve) // //throw new Error('then Error') // return 'aaa'; // },err=>{ // console.log(err) // return 10000 // }).then((resolve)=>{ // console.log(resolve) // }) // primise1.finaally(()=>{ // console.log('finaally') // return primise // }).then(value=>{ // console.log(value) // },resone=>{ // console.log(resone) // }) primise1.then(value=>console.log(value)) .catch(reasonn=> console.log(reasonn))  // primise.then().then().then().then(value=>console.log(value),err=>{ // console.log(err) // }) // MyPromise.all(['a','b',primise,primise1,'c']).then(res=>console.log(res),rej=>console.log(rej)) // MyPromise.resolve(100).then(value=>console.log(value)) // MyPromise.resolve(primise).then(value=>console.log(value)) // var cc = new promise ((res,rej)=>{// res(100) //) // return p // }) // p.then(()=>{},(err)=>{ // console.log(err) // })Copy the code