“This is the 16th day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.

portal

Tear Promise from zero hand, master the realization of the Promise principle (1) of the basic structure of the Promise

From scratch tear Promise, grasp the Promise realization principle (2) of the basic version of the Promise

Tear Promise from scratch, Master Promise realization principle (3) Callback what is hell

From scratch tear Promise, master the Promise realization principle (4) then method chain call preliminary implementation

From scratch tear Promise, master the Promise realization principle (5) then method chain call of the advanced implementation

Why is the callback of then method asynchronous microtask

(7) Then the core method of chain call resolvePromise

(8) The core method of chain call of then method resolvePromise is explored again

(9) Then method chain call core method resolvePromise complete

Tear Promise from scratch, master the realization principle of Promise (10)then method to complete all

Test whether all promises comply with PromiseA+ by learning how to implement promises (11)

What? Promise.resolve() can also return a failed Promise (12)

review

After the introduction of the last article, we completed the Promise, catch, Reject, and resolve methods, and now Promsie looks like this.

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const resolvePromise = (promise, x, resolve, reject) = > {
  / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * to determine whether x and promsie the same promise, Prevent an infinite loop *********************//////*********
  if(x === promise) throw new TypeError('Chaining cycle detected for promise #<Promise>')
  // 1. Determine whether 'x' is a base type or a reference type.
  if(x ! = =null && /^(object|function)$/.test(typeof x)){
    let then 
    Then attribute (' x.chen ') on 'x'. Reject 'if an exception is reported
    try{
      then = x.then
    }catch(e){
      reject(e)
    }
    //3. Determine if 'then' is a function. If it is a function, then it is' Promise ', if not 'resolve'
    if(typeof then === 'function') {let called = false / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
      try{
        then.call(x, (y) = > {
          if(called) return / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
          called = true
          resolvePromise(promise, y, resolve, reject)
        },(r) = > {
          if(called) return/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
          reject(r)
        })
      }catch(e){
        if(called) return/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
        reject(e)
      }
    }else{
      resolve(x)
    }
  }else{
    // Base type data directly resolve
    resolve(x)
  }
}
class Promise{
  constructor(executor){

    this.state = PENDING
    this.value = undefined
    this.reason = undefined
    / / store onFulfilled
    this.onResolvedCallbacks = []
    / / store onRejected
    this.onRejectedCallbacks = []
    const resolve = (value) = > {
       // If we find that value is a Promise, we need to call value's then method to recursively resolve it
      if(value instanceof Promise) {return value.then(resolve,reject); // recursive parsing
      }
      if (this.state === PENDING) {
        this.value = value
        this.state = FULFILLED
        // The promise instance will call ondepressing after its state changes
        this.onResolvedCallbacks.forEach(fn= > fn())
      }
    }

    const reject = (reason) = > {
      if (this.state === PENDING) {
        this.reason = reason
        this.state = REJECTED
        // onRejected called after the promise instance state changes
        this.onRejectedCallbacks.forEach(fn= > fn())
      }
    }
    try {
      // An error in the execution of the executor function will cause the Promise to fail
      executor(resolve,reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onFulfilled, onRejected){
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v= > v
    onRejected = typeof onRejected === 'function' ? onRejected : err= > { throw err }
    let promise = new Promise((resolve, reject) = > {
        
        switch(this.state){
          case FULFILLED:
              setTimeout(() = > {
                try{
                  let x = onFulfilled(this.value)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })   
              break
          case REJECTED:
              setTimeout(() = > {
                try{
                  let x = onRejected(this.reason)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })   
              break
          default:
            this.onResolvedCallbacks.push(() = > {
              setTimeout(() = > {
                try{
                  let x = onFulfilled(this.value)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })
            })
            this.onRejectedCallbacks.push(() = > {
              setTimeout(() = > {
                try{
                  let x = onRejected(this.reason)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })
            })
        }
    })
    return promise
  }
  catch(onRejected){
    return this.then(null, onRejected)
  }
  static rsolve(value){
    return new Promise((resolve,reject) = >{ resolve(value); })}static reject(reason){
      return new Promise((resolve,reject) = >{ reject(reason); }}})Copy the code

This article introduces

  • What this article mainly accomplishes is,finallyMethod, this method is often asked in the interview, is how to achieve.finallyThe method is the prototypical method.

Hand to tearfinallymethods

  • The finally method accepts a callback that is executed whether the Promise succeeds or fails.

  • Finally methods are implemented internally through then methods and promise.resolve.

  • Principle is as follows

finally(cb){
  return this.then(
    (y) = > {
      return Promise.resolve(cb()).then(() = > y)
    },
    (r) = > {
      return Promise.resolve(cb()).then(() = > {throw r})
    }
  )
}

Copy the code

parsingfinallyRealize the principle of

  • I believe that you and I saw the above implementation, feel the brain buzzing, the heart of ten thousand grass mud horse pentium, write what shit.
  • Here I will answer your doubts through four small examples, becausefinallyThe implementation of theresolveIn order to facilitate my expression, I marked some serial numbers in the following two pictures for you to compare according to my ideas.

Key code for finally implementation

Key code for the Resolve implementation

  • The sequence numbers used to explain the execution logic of resolve are those identified in the above two images. If you are not familiar with the resolve implementation process, you can read the previous article through the portal, which specifically describes the implementation of Resolve.

  • Case 1

    Promise.resolve('ok').finally(() = > { 
        return new Promise((resolve,reject) = >{
            setTimeout(() = > {
                resolve('inner ok')},1000);
        })
    }).then((data) = > {
        console.log('success', data)
    }, (err) = > {
        console.log('failure', err)
    })
    Copy the code
    • Native Promise execution results (browser console print)

    • Run the example based on the code we implemented, in the following order.

      Promise.resolve(‘ OK ‘) –> call finally to execute F1 where y is OK –> execute R1 –>F3 The Promsie value that finally returns success is inner OK –> execute promise.resolve in R2 F1 Returns a Promise of success –> execute F5

      At this point, F5 returns y(OK), that is, finally returns a successful Promise of OK –> then executes a successful callback, and prints’ successful OK ‘.

  • Example 2

    Promise.resolve('ok').finally(() = > {
        return new Promise((resolve,reject) = >{
            setTimeout(() = > {
                reject('inner ok')},1000);
        })
    }).then((data) = > {
        console.log('success', data)
    }, (err) = > {
        console.log('failure', err)
    })
    Copy the code
    • Native Promise execution results (browser console print)

    • Run the example based on the code we implemented, in the following order.

      Promise.resolve(‘ OK ‘) –> call finally to execute F1 where y is OK –> execute R1 –>F3 finally returns the Promsie that failed because inner OK –> execute R3 F1 Resolve returns a failed Promise because inner OK –> then does not execute F5. Then replaces the second failed callback by default, so F1 returns a failed Promsie because inner OK, Inner OK –> call then to execute the failed callback and print ‘failed inner OK’

  • I’m not going to take you through case 3 and case 4. You can analyze it the way I do, provided you’ve written promises yourself, otherwise it will be hard to analyze. If you don’t know promises very well, you can read my series of articles and implement a Promise from scratch.

portal

Tear Promise from zero hand, master the realization of the Promise principle (1) of the basic structure of the Promise

From scratch tear Promise, grasp the Promise realization principle (2) of the basic version of the Promise

Tear Promise from scratch, Master Promise realization principle (3) Callback what is hell

From scratch tear Promise, master the Promise realization principle (4) then method chain call preliminary implementation

From scratch tear Promise, master the Promise realization principle (5) then method chain call of the advanced implementation

Why is the callback of then method asynchronous microtask

(7) Then the core method of chain call resolvePromise

(8) The core method of chain call of then method resolvePromise is explored again

(9) Then method chain call core method resolvePromise complete

Tear Promise from scratch, master the realization principle of Promise (10)then method to complete all

Test whether all promises comply with PromiseA+ by learning how to implement promises (11)

What? Promise.resolve() can also return a failed Promise (12)

There are a few other Promise methods that I’ll look forward to giving a thumbs up.