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


One, foreword

Resolve and promise.Reject are two static apis (class methods) that implement Promise.

  • Promise.resolveCreate and return a successful promise;
  • Promise.rejectCreate and return a failed promise;
  • Promise.resolveWait for the asynchronous operation to complete;Promise.rejectFailure returns directly;

This, will realize the Promise two instances API (prototype method) : Promise. The prototype. The catch and Promise. Prototype. Finally;

Note: Catch and finall are high-frequency apis used in Promise, which are emphasized in the interview questions.


Second, Promise. Prototype. The catch

MDN Resources

  • The. Catch method handles the case where a Promise is rejected and returns a failed Promise;
  • Actual behavior andPromise. Prototyope. Then (undefined, onRejected)The same;
  • Therefore, it can be understood as a then method that only deals with the Promise failure state;

Note: A Promise fails when a reject() is called or an exception occurs.

1, test the native promise.prototype.catch

Promise.reject(new Promise((resolve, reject) = >{ / / directly
  setTimeout(() = > {
    resolve(200)},1000);
})).then((data) = > {  // Do not process the failed state, proceed to the next then processing
  console.log('onFulfilled', data)}). The catch (err= >{       // equivalent to a then that deals only with failed states
  console.log('onRejected:', err)
})

OnRejected :Promise {
      
       }
      
Copy the code

2. Principle analysis

  • Promise.rejectA promise that will return a failed state;
  • Failed promises do not wait for the result of asynchronous processing to return: an internal callreject()Will directly throw a promise in a PENDING state;
  • Because the then function is not passedonRejectedCallback processing continues to the next THEN processing;
  • So, failed promises go into catch methods;

3. Function realization

Use the same code to test, because the prototype method promise.prototype. catch has not been implemented, so an error is reported;

In the Promise class, add the prototype method catch() :

  // Prototype method catch
  // errorFn: indicates the handling of the failure
  catch(errorFn){
    // A then that only deals with failed states
    return this.then(null, errorFn)
  }
Copy the code

The effect of the test is the same as the original Promise, and the PENDING Promise is returned directly:

Promise {state: 'PENDING', value: undefined, reason: undefined, onResolvedCallbacks: [], onRejectedCallbacks: [] } errCopy the code

4. Capture mechanism

  • In the try… catch… An error thrown by a catch will be caught by the most recent catch and will not bubble upward unless the catch continues to throw an error externally;

  • An error thrown in a Promise object can be chain-called because it is caught by promise.prototype. catch and still returns a Promise object.

  • However, if a Promise throws an error but does not use a catch() method to specify the error handling callback, then the thrown error is not passed on to the outer code.


Three, Promise. Prototype. Finally

MDN Resources

1, test the native Promise. Prototype. Finally

1. Finally of the successful Promise

let p = new Promise((resolve, reject) = >{
  setTimeout(() = > { // Question 1: Does finally wait for an asynchronous operation to complete?
    resolve(1000)},3000);
}).finally(() = >{     // Question 2: When a Promise succeeds, does it enter finally?
  console.log('finally')
}).then((data) = >{    // Question 3: Can I continue after finally?
  console.log('then', data)  // Question 4: Where does the data in then come from?
});

"Finally" + "then 1000" after 3 seconds
Copy the code

Analysis:

  • The finally method waits for the asynchronous operation ina Promise to complete;
  • When the Promise succeeds, the finally method is executed; Execute both success and failure.
  • Finally after execution, you can continue. Then, indicating that a promise is returned internally;
  • If a Promise succeeds, the content of resolve will be passed through to the next THEN via finally.

Note: Data cannot be obtained in finally.

2. Finally of the failed Promise

let p = new Promise((resolve, reject) = >{
  setTimeout(() = > {
    reject(1000)},3000);
}).finally(() = >{  // Question 1: When a Promise fails, does it enter finally?
  console.log('finally')
}).then((data) = >{ // Question 2: If a Promise fails, does it enter then? Where does data come from?
  console.log('then', data)
}).catch(e= >{     // Question 3: When a Promise fails, does it enter a catch? Where does e come from?
  console.log('catch', e)
})

// "finally" + "catch 1000" after 3 seconds
Copy the code

Analysis:

  • When a Promise fails, the finally method is also executed; (Execute both success and failure)
  • When a Promise fails, the content of reject is passed down through finally; (Finally returns a failed promise, then does not process a failure and enters a catch)

3. In finally of the success state Promise, return the success Promise

let p = new Promise((resolve, reject) = >{
  setTimeout(() = > {
    resolve(1000)},3000);
}).finally(() = >{
  console.log('finally')
  return new Promise((resolve, reject) = >{
    resolve(2000)
  })
}).then((data) = >{ // question 1: whether to enter then, data value is 1000 or 2000
  console.log('then', data)
}).catch(e= >{     // Question 2: Is there a catch? Is e 1000 or 2000
  console.log('catch', e)
})

"Finally" + "then 1000" after 3 seconds
Copy the code
Then, data is 1000; Finally uses the successful outcome of the previous promise;Copy the code

4. In finally of the successful Promise, return the failed Promise

let p = new Promise((resolve, reject) = >{
  setTimeout(() = > {
    resolve(1000)},3000);
}).finally(() = >{
  console.log('finally')
  return new Promise((resolve, reject) = >{
    reject(2000)
  })
}).then((data) = >{ // question 1: whether to enter then, data value is 1000 or 2000
  console.log('then', data)
}).catch(e= >{     // Question 2: Is there a catch? Is e 1000 or 2000
  console.log('catch', e)
})

"Finally" + "catch 2000" after 3 seconds
Copy the code
Catch is entered, e is 2000; Note that finally uses the failed result of its own internal Promise;Copy the code

By comparing 3 and 4 cases, it can be concluded that:

  • When a Promise in finally succeeds, the last Promise is returned;
  • When a Promise in finally fails, use your own Promise result to return;

5. In finally of the failed Promise, return the success Promise

let p = new Promise((resolve, reject) = >{
  setTimeout(() = > {
    reject(1000)},3000);
}).finally(() = >{
  console.log('finally')
  return new Promise((resolve, reject) = >{
    resolve(2000)
  })
}).then((data) = >{ // question 1: whether to enter then, data value is 1000 or 2000
  console.log(data)
}).catch(e= >{     // Question 2: Is there a catch? Is e 1000 or 2000
  console.log('catch', e)
})

// "finally" + "catch 1000" after 3 seconds
Copy the code
Catch is entered, e is 1000; Finally uses the failed result of a previous Promise.Copy the code

6. In finally of failed Promise, return failed Promise

let p = new Promise((resolve, reject) = >{
  setTimeout(() = > {
    reject(1000)},3000);
}).finally(() = >{
  console.log('finally')
  return new Promise((resolve, reject) = >{
    reject(2000)
  })
}).then((data) = >{ // question 1: whether to enter then, data value is 1000 or 2000
  console.log(data)
}).catch(e= >{     // Question 2: Is there a catch? Is e 1000 or 2000
  console.log('catch', e)
})

"Finally" + "catch 2000" after 3 seconds
Copy the code
Catch is entered, e is 2000; Note that finally uses the failed result of its own Promise;Copy the code

By comparing 3, 4, 5, and 6, it can be concluded that:

  • Regardless of whether a promise before finally succeeds or fails, if a promise in finally succeeds, the last promise is returned. Whenever a Promise in finally fails, use its own Promise result as a return;

2. Principle analysis

Summarize the above 6 cases:

  • Finally is the prototype method for Promise;
  • Finally can’t get data data;
  • Finally internally continues to return a promise;
  • Finally is executed regardless of whether a promise before finally succeeds or fails;
  • The finally method waits for the asynchronous operation ina Promise to complete;
  • No matter whether a promise before finally succeeds or fails, after finally execution is complete, the result of the last promise will continue to be passed down.
  • No matter whether a promise succeeds or fails before finally, as long as a promise succeeds in finally, the last promise result will be returned. If a Promise in finally fails, return your own Promise result.

3. Function realization

1. Prototype method, success and failure are implemented

// Prototype method
Promise.prototype.finally = function(cb){
  // Finally internal call then returns promise
  return this.then(() = >{
    cb()  // Cb will be executed successfully
  },() = >{
    cb()  // Cb is executed on failure})}Copy the code

The above code implements:

  • Finally is the prototype method for Promise;
  • Finally can’t get data data;
  • Finally internally continues to return a promise;
  • Finally is executed regardless of whether a promise before finally succeeds or fails;

2, wait for the Promise execution to complete

Finally internally calls then, which ultimately returns a promise, and cb is executed on the success or failure of the promise;

So, wait for the promise to complete; Wrap promise.resolve () with wait effects; (Note: promise.reject () has no waiting effect and the error is returned directly)

Promise.prototype.finally = function(cb){
  return this.then((data) = >{
    return Promise.resolve(cb()).then((dataCb) = >data)
  },() = >{
    return Promise.resolve(cb()).then((n) = >{throwerr}); })}Copy the code

// Todo code parsing

The above code implements:

  • The finally method waits for the asynchronous operation ina Promise to complete;

Four, the end

This paper, the main implementation Promise two instances API (prototype method) : Promise. Prototype. Catch and Promise. Prototype. Finally, mainly involves the following several points:

  • Promise.prototype.catchFunction testing, principle analysis, source code implementation;
  • Promise.prototype.finallyFunction testing, principle analysis, source code implementation;

Next, continue implementing the core static API (class methods) of Promise: promise.all;


Maintenance record

  • 20211104
    • Add finally test analysis and conclusion of 6 cases;
  • 20211105
    • Add MDN links and screenshots;