Focus onThe front small OuRead more original technical articles

Review: Progressive interpretation of Promise source code (1) review: Progressive interpretation of Promise source code (2)

Complete code + notes, can be read

Promise. Prototype. Then – the source code

/** Then attribute of the Promise prototype, which points to the function * onFulfilled: onFulfilled: this is a pity. The onRejected handler, a callback that is executed when a contract is rejected * supports an infinite chain of callbacks, with each THEN () method returning a new Promise instance */
Promise.prototype.then = function (onFulfilled, onRejected) {
  // console.log(this, 'then') // this points to an instance of Promise returned before THEN ()
  // console.log(this.constructor) // constructor points to the Promise constructor
  // console.log(this.constructor === Promise) // true

  /* Create a new Promise instance (equivalent to new Promise(noop)), pass the empty method noop as the executor function note: Each call to.then() creates a new Promise instance, but calling the next.then() changes the _Deferreds array of the last Promise instance (into the next Handler instance)! * /
  var prom = new this.constructor(noop) // -> var prom = new Promise(noop) -> var prom = new Promise(()=>{})
  // Console. log(PROM) // Promise {_state: 0, _handled: false, _value: undefined, _deferreds: []}, new date
  // Console. log(new Promise(noop)) // Promise {_state: 0, _handled: false, _value: undefined, _deferreds: []}, likewise

  /** * Handle () {this: then(); /** * New Handler(onFulfilled, onRejected, PROM) : / /
  handle(this.new Handler(onFulfilled, onRejected, prom))

  return prom // Returns the newly created contract instance for chain invocation
}

function noop() {}
Copy the code
  • thenPoint to a functionthis, pointing to the currentthenBefore the returnedPromiseInstance, thereforethis.constructorPoint to thePromiseThe constructor
  • Each callPromise.thenWhen:
    • The method of emptynoopAs an executor function, callednew this.constructor()Create a new nullPromiseThe instance
    • I’m going to create a new oneHandlerInstance, and then callhandle()methods
    • Eventually, the newly created term instance is returned to support infinite chain callbacks
    • “Call the next one.then()Will be the last onePromiseThe instance_deferredsArray changes “, can be studied later

Handler constructor – source code

/ / This is a big pity; / / This is a big pity; / / This is a big pity; / / This is a big pity; Reject callback * argument PROMISE: new empty promise instance */
function Handler(onFulfilled, onRejected, promise) {
  this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null // Whether there was a successful callback, if not, null is assigned
  this.onRejected = typeof onRejected === 'function' ? onRejected : null // Whether there is a failure callback, if there is no null
  this.promise = promise // Handler's promise points to PROM, the new promise instance created in.then()
  // console.log(this.promise, 'new Handler')
  // console.log(this)
}
Copy the code
  • Receives three parameters: successful callback, failed callback new nullpromiseThe instance

Handle () – Test code

  • On the basis of the source code to simplify, convenient to do stage testing
/** The handle() method used for testing * the Promise instance returned before self: then() * the Handler instance created with the deferred argument */
function handle(self, deferred) {
  // console.log(self)
  // console.log(deferred)

  [Function (anonymous)], // This is a big pity. OnFulfilled: // This is a big pity. OnFulfilled: // This is a big pity. [Function (anonymous)], // the promise attribute points to a new promise instance _state: 0, _handled: false, _value: undefined, _deferreds: [] } } */

  /* If the settlement value of the returned contract instance is of type PROMISE, _state=3 */
  while (self._state === 3) {
    self = self._value // Assign the resolution value to the returned contract instance
  }

  /* If the returned contract instance is pendding, _state=0, the resolve() or reject() methods */ have not yet been executed
  if (self._state === 0) {
    self._deferreds.push(deferred) // Put the Handler instance into the instance's _deferrends array, return, and wait
    console.log(self)
    return
  }

  /* Marks the current promise._handled as true */
  self._handled = true
  console.log(self)

  /* The callback is handled asynchronously through the event loop (note: this is asynchronous!) * /
  Promise._immediateFn(function () {
    var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected // Get the onFulfilled or onRejected process

    /* Perform your own callback */ if there is ondepressing or onRejected callback function
    try {
      /** * () : perform onFulfilled or onRejected () * self._value: then() returns the fulfilled Promise instance value/reject reason */
      cb(self._value) // Perform the callback
    } catch (e) {
      /* If an error is thrown, the reject() method is called, taking the promise (new Promise instance) of the Handler instance you created and the reason for the error */
      reject(deferred.promise, e)
      return}})}Copy the code
  • thenPrevious return period instance, according to_stateDifferent values do different things
    • Returns a non-pending term that will eventually be executedthenHandler in
    • If a pending contract is returned, it is not executedthen, butwillthenGenerated in theHandlerInstance in thethenbeforePromiseThe instance_deferredsAn array of
  • performthenThe handler for theasynchronousIs executed after all synchronization operations have been performed

Promise.prototype. Then – Phase test

new Promise((resolve, reject) = > {}).then(() = > {
  console.log(3) // Then is an unresolved contract. No handler is executed until the contract is resolved
})
/* When handle() is handled, self._state is set to 0, and the Handler instance is placed in the _deferrends array of the Handler instance and no further action is taken. Self is set to: Promise {_state: 0, _handled: false, _value: undefined, _deferreds: [ Handler { onFulfilled: [Function (anonymous)], onRejected: null, promise: Promise {_state: 0, _handled: false, _value: undefined, _deferreds: []} } ] } */

new Promise((resolve, reject) = > {
  /* After the first resolve or reject is actually executed, subsequent resolve or reject are not executed, and only the test results are merged */

  resolve(3) // Prints res as 3, resolving the value as a basic type
  /* self is the Promise {_state: 1, _handled: true, _value: 3, _deferreds: []} */
  resolve({ val: 3 }) // Prints res as {val: 3}, resolving the value as a normal object
  /* self is the Promise {_state: 1, _handled: true, _value: {val: 3}, _deferreds: []} */
  resolve(new Promise(() = > {})) // Resolve pending instances without printing res
  /* This is a big pity. /* This is a big pity. /* This is a big pity
  resolve(Promise.resolve(3)) // Print the periodic instance of res being 3 and the solution value being fullfilled, and assign the solution value of fullfilled to self
  /* self is the Promise {_state: 1, _handled: true, _value: 3, _deferreds: []} */
  resolve({
    // The solution value is thenable object
    value: 3.then: function () {
      console.log(this) // { value: 3, then: [Function: then] }
      console.log(this.value) / / 3}})/* self与resolve(new Promise(() => {}))相同 */
}).then((res) = > {
  console.log(res) // The resolution value of the Promise returned before then()
})

new Promise((resolve, reject) = > {
  reject(3) // Prints res as 3
  /* self is the Promise {_state: 2, _handled: true, _value: 3, _deferreds: []} */
}).then(null.(err) = > {
  console.log(err) // Then () returns the reason for rejecting the Promise
})
Copy the code
  • There is a general outline of the chain callback:
    • According toPromiseThe state of the instance, gets its resolution value/rejection reason, and executes the appropriate handler (onResolveoronReject)
  • peddingState of the contract callthenLater, will bethenGenerated in theHandlerInto which instances are put_deferredsAn array of

Promise. Prototype. Catch – the source code

/** The catch attribute of the Promise prototype points to the function * parameter onRejected: the onRejected handler, which executes a callback on a contract rejection and supports an infinite chain of callbacks. Each catch() method returns a new Promise instance */
Promise.prototype['catch'] = function (onRejected) {
  return this.then(null, onRejected)
}
Copy the code
  • inPromise.prototype.thenDo a layer of encapsulation, only receiveonRejectedThe handler

Promise.prototype. Catch – Stage test

new Promise((resolve, reject) = > {}).catch(() = > {
  console.log(3) // catch is an unresolved contract, and no handler is executed until the contract is resolved.
})

new Promise((resolve, reject) = > {
  /* After the first resolve or reject is actually executed, subsequent resolve or reject are not executed, and only the test results are merged */

  reject(4) // 4, the rejection reason is the basic type
  /* self is the Promise {_state: 2, _handled: true, _value: 4, _deferreds: []} */
  reject({ val: 4 }) // {val: 4}, the rejection reason is common object
  /* self is the Promise {_state: 2, _handled: true, _value: {val: 4}, _deferreds: []} */
  throw Error('error! ') // 'Error: error! ', throws an error
  /* self as Promise {_state: 2, _handled: true, _value: Error: Error! , _deferreds: [] } */
  reject(new Promise(() = > {})) // 'Promise {_state: 0, _handled: false, _value: undefined, _deferreds: []}'
  /* self as Promise {_state: 2, _handled: true, _value: Promise {_state: 0, _handled: false, _value: undefined, _deferreds: [] }, _deferreds: [] } */
  reject(Promise.resolve(3)) // 'Promise {_state: 1, _handled: false, _value: 3, _deferreds: []}
  /* self as Promise {_state: 2, _handled: true, _value: Promise {_state: 1, _handled: false, _value: 3, _deferreds: [] }, _deferreds: [] } */
}).catch((err) = > {
  console.log(err) // The rejection reason for the return Promise before catch()
})
Copy the code
  • withPromise.prototype.thenThe results are roughly the same and need to be distinguishedcatchThe reason for the rejection of the previous contract isPromiseCase of instance

Summary of Implementation results

  • A singlePromise.prototype.thenandPromise.prototype.catchChain callback (several not yet implemented)

As of the code in this section →