I've lost count of the number of versions I've read of a handwritten promise. But I didn't write one myself. Last night with my colleagues he said it was simple, I asked him to write a scene, good guy to write after the promise how can not be used, but still strong finally write out. Make your own wave while there's still heat

First, to MDN carefully review the use of promise in the end

For the record: Promise doesn’t have the source code; its underlying browser, V8, is already implemented. It’s actually implemented in c++

2. Make promises in your head

      class myPromise {
        constructor () {
          this.status = 'pending'
        }
        then () {}
        catch () {}
        finally () {}
        all () {}
        This is a big pity. /** * allSettled * Until all promises are settled, which is a big pity or rejected. Return a promise that completes after all promises have completed. With an array of objects, each corresponding to the result of each promise. * /
        allSettled () { }
        any () {}
        race () {}
        reject () {}
        resolve () {}
      }
Copy the code

Now that we have the basic structure out, let’s make a new promise and see what it looks like

      const p = new Promise((resolve, reject) = >{})console.log(p)
Copy the code

This Promise is a pending state. Only when we invoke ‘resolve’, it will become a pity state, and when we invoke ‘Reject’, it will become ‘Rejected’

— How come this state looks like this… Well, let’s define the constructor based on what it prints

    constructor (handle) {
          this['[[PromiseState]]'] = 'pending'
          this['[[PromiseResult]]'] = undefined
        }
Copy the code

Third, parsing the implementation

1. When we new a promis instance, we pass a function to the promise, so we receive a function (Handle) in the promise, which contains a resolve and a reject call, so handle has two parameters

2. According to the printed results, we will change the promiseState and put the result set into the PromiseResult when we resolve or reject

      class myPromise {
        constructor (handle) {
          this['[[PromiseState]]'] = 'pending'
          this['[[PromiseResult]]'] = undefined
          handle((res) = > {
            this['[[PromiseState]]'] = 'fulfilled'
            this['[[PromiseResult]]'] = res
          }, (err) = > {
            this['[[PromiseState]]'] = 'rejected'
            this['[[PromiseResult]]'] = err
          }) // Execute immediately
        }
        then () {}
        catch () {}
        finally () {}
        all () {}
        This is a big pity. /** * allSettled * Until all promises are settled, which is a big pity or rejected. Return a promise that completes after all promises have completed. With an array of objects, each corresponding to the result of each promise. * /
        allSettled () { }
        any () {}
        race () {}
        reject () {}
        resolve () {}
      }
      const myP = new myPromise((resolve, reject) = >{})console.log('myP', myP)
Copy the code

—- Yes

then

Then receives two callback functions, which we are used to writing error messages into a catch

        then (successCallback, failCallback) {
          if (this['[[PromiseState]]'= = ='fulfilled') {
            successCallback && successCallback(this['[[PromiseResult]]'])}else {
            failCallback && failCallback(this['[[PromiseResult]]'])}}Copy the code

—- IF I write ‘then’ I can do ‘resolve’, ‘reject’ but if I add ‘setTimeout’ I can do nothing. Writing then this way is an immediate function. So it’s gonna have to be remodeled

4. You can’t execute it immediately, so you can store the callback first and then execute it in resolve or Reject

Note: Only resolve or reject is called before the callback is executed

 class myPromise {
        constructor (handle) {
          this['[[PromiseState]]'] = 'pending'
          this['[[PromiseResult]]'] = undefined
          this.resolveFn = undefined
          this.rejectFn = undefined
          handle(this.#resolve.bind(this), this.#reject.bind(this)) //
        }
        /** * I use resolve and reject as internal functions */ for maintenance purposes
        #resolve (val) {
          this['[[PromiseState]]'] = 'fulfilled'
          this['[[PromiseResult]]'] = val
          console.log('this.resolveFn'.this.resolveFn)
          this.resolveFn(val)
        }
        #reject (err) {
          this['[[PromiseState]]'] = 'rejected'
          this['[[PromiseResult]]'] = err
          this.rejectFn(err)
        }
        then (successCallback, failCallback) {
          this.resolveFn = successCallback
          this.rejectFn = failCallback
        }
     }
      const myP = new myPromise((resolve, reject) = > {
        setTimeout(() = > {
          resolve('jdjkkjdd')},1000)
      })
      myP.then(res= > {
        console.log('res', res)
      })
      console.log('myP', myP)
Copy the code

5. Let’s talk about multiple ‘THEN’ s, not chained ‘THEN’ s

      const p = new Promise((resolve, reject) = > {
          resolve('resulr')
      })
      p.then(res= > {
        setTimeout(() = > {
          console.log('111', res)
        }, 1000)},err= > {
        console.log(err)
      })
      p.then(res= > {
        console.log('2222',res)
      })
      console.log(p)
     // ...
     // Multiple "then" like this
Copy the code

The result is still normal because I added setTimeout to 111, but the promise we wrote will only be executed once, why? This [‘[[PromiseResult]]’] will be overwritten. Therefore, we will store the resolveFn and rejectFn callback functions as arrays

 class myPromise {
        constructor (handle) {
          this['[[PromiseState]]'] = 'pending'
          this['[[PromiseResult]]'] = undefined
          this.resolveFn = []
          this.rejectFn = []
          handle(this.#resolve.bind(this), this.#reject.bind(this)) //
        }
        /** * I use resolve and reject as internal functions */ for maintenance purposes
        #resolve (val) {
          this['[[PromiseState]]'] = 'fulfilled'
          this['[[PromiseResult]]'] = val
          // this.resolveFn && this.resolveFn(val)
          // Push in from the back and pull out from the top
          const run = () = > {
            let cb
            while (cb = this.resolveFn.shift()) {
              cb && cb(val)
            }
          }
          run()
        }
        #reject (err) {
          this['[[PromiseState]]'] = 'rejected'
          this['[[PromiseResult]]'] = err
          // this.rejectFn && this.rejectFn(err)
          // Push in from the back and pull out from the top
          const run = () = > {
            let cb
            while (cb = this.rejectFn.shift()) {
              cb && cb(err)
            }
          }
          run()
        }
        then (successCallback, failCallback) {
          this.resolveFn.push(successCallback)
          this.rejectFn.push(failCallback)
        }
     }
      const myP = new myPromise((resolve, reject) = > {
        setTimeout(() = > {
          resolve('jdjkkjdd')},1000)
      })
      myP.then(res= > {
        console.log('res', res)
      })
      myP.then(res= > {
        console.log('2222', res)
      })
      console.log('myP', myP)
Copy the code

I can’t take a break. Promise is too difficult ,,,, look good remember a key three even oh ~ later will continue to update to complete