In the previous logic, just some basic functions of promise, carried on the principle analysis, and did not capture and process the exceptions, then we need to capture these exceptions, and improve our code.
Where in the logic do you need to catch exceptions:
- The code inside the executable is abnormal.
then
methodsSuccess callback, code exception;then
methodsFailure callback, code exception;then
methodsAsynchronous logic callback successfully, code exception;then
methodsAsynchronous logic failed callback, code exception;
For the above code exceptions, we need to catch these errors and throw them, and if the exception occurs, the code can continue to execute, we need to use the try… Catch method, which calls reject if an error occurs and passes the reason for the error.
**try… The catch is introduced: * *
try... catch
: The program can continue execution when errors occurtry
: Monitors code blocks where exceptions may occurcatch
Capture:try
The error that occurs inside is handled
We throw an exception in a catch, the test and new code in the article is only written in the changed part, the global code is at the end of the article.
1. Code in the executor is abnormal:
Constructor (executor) {try {// The executor receives two arguments executor(this.resolve, this.reject); } catch (error) {// If an exception occurs, call reject, this.reject(error); }}Copy the code
Test cases in **index.js** :
const testPromise = require ("./test-promise"); Let promise = new testPromise ((resolve, reject) => {// throw new TypeError ("executor error"); }) // 6.1 Test executor error promise.then(value => {console.log(value); }, reason => {console.log(" catch error >>>", reason); })Copy the code
Execution Result:
** An exception occurred in the current THEN callback, which needs to be caught and passed to the next THEN call, which needs to be caught in the reject method of the next THEN callback.
TestPromise * *. * * in js:
if (this.status === FULFILLED) { setTimeout(() => { try { let x = successCallback(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) {// Call the reject method of the next then method, not this.reject reject(error); }}}, 0)Copy the code
Test cases in **index.js** :
If (value => {// then throw new Error ("successCallback Error "); if (value => {then throw new Error ("successCallback Error "); }) // In the second then method catch. Then (value => {}, reason => {console.log(" catch [then method successful callback] error >>>", reason); })Copy the code
Execution Result:
**3. Then method failed callback code exception: ** principle same as successful callback
TestPromise * *. * * in js:
else if (this.status == REJECTED) { // failCallback(this.reason); setTimeout(() => { try { let x = failCallback(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); }}}, 0)Copy the code
Test cases in **index.js** :
Then (value => {},reason => {throw new Error ("failCallback Error "); }) // Catch. Then (value => {}, reason => {console.log(" catch [then method failed callback] error >>>", reason); })Copy the code
Execution Result:
5. Then method ** asynchronous logic failed callback **** : ** Same as above, direct code
TestPromise * *. * * in js:
While (this.successValue.length) this.successValue.shift()(this.value) // change to 👇👇👇👇 while (this.successValue.length) this.successValue.shift()() // reject while (this.failreason.length) This.failreason.shift ()(this.value) // change to 👇👇👇👇 while (this.failreason.length) this.failreason.shift ()() -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- / / if the code for the processing, has put the current call value passed to the next, then, it can be resolve and reject method is executed directly before, don't need to preach value, 👆 else {// try.. // This.successValue. push(successCallback); // this.failReason.push(failCallback); this.successValue.push(() => { setTimeout(() => { try { let x = successCallback(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); }}}, 0)); this.failReason.push(() => { setTimeout(() => { try { let y = failCallback(this.reason); reject(y); } catch (error) { reject(error); }}}, 0)); return; }Copy the code
**index.js**
Promise. then(value => {throw new Error (" async Error "); },reason => {console.log(" catch [then method async callback] 111>>>", reason); }) // In the second then method catch. Then (value => {}, reason => {console.log(" catch [then method asynchronous callback] error >>>", reason); })Copy the code
Test results:
At this point, exception catching in logic is complete:
TestPromise:
// Define state const PENDING = "PENDING "; const FULFILLED = "fulfilled"; const REJECTED = "rejected"; Class testPromise {/** * callback received via constructor * The constructor cannot be called directly, but must be called automatically when the object is created using the new operator, * When we call new myPromise() externally to generate an instance, the Consctructor constructor executes, and the executor executor immediately executes. * * Executor stands for executor, */ constructor (executor) {try {// The executor accepts two arguments executor(this.resolve, this.reject); } catch (error) { this.reject(error); }} /** * The initial state is waiting */ status = PENDING, which is unique to each promise; // Define success value value = undefined; // Define failed value reason = undefined; // successValue = undefined; // Repeat then, store successValue = []; FailReason = []; failReason = []; Resolve = value => {// If (this.status!) {// If (this.status! == PENDING) return; this.status = FULFILLED; // This. Value = value; // Handle asynchron to determine if there is successValue, and if there is, call successCallback and pass in the value argument to that call // console.log("successValue>>>", this.SuccessValue); // [Function (anonymous)] /** * 1. This will be a big pity. The next step is that successValue will store successCallback, which will be fulfilled if the resolve method is executed 2 seconds later. This will be a pity. If (this.successValue) this.successValue(this.value); * * 2. Call the then method repeatedly, so that the callback functions stored in the array are executed * and arranged in reverse order. * while (this.successValue.length) this.successValue.shift()(this.value); */ while (this.successValue.length) this.successValue.shift()(); } reject = reject = reason => {if (this.status! == PENDING) return; this.status = REJECTED; // This. Reason = reason; // if (this.failReason) this.failReason(this.reason); while (this.failReason.length) this.failReason.shift()(); } /** * then method * determines the state * defined on the Promise prototype and specifies the Resolved state callback or the Rejected state callback. */ Then (successCallback, failCallback) {/** * And specify the corresponding callback function based on the state * so where is the value after success, where is the value after failure, */ let promise2 = new testPromise ((resolve, reject) reject) => { if (this.status === FULFILLED) { setTimeout(() => { try { // 2. Let x = successCallback(this.value); Resolve (x); // resolve(x); /** * If the value is normal, call the resolve method and pass the current value to the next Promise. * And pass the corresponding success value or failure reason to the next Promise object * * If it is asynchronous and calls resolve or reject repeatedly, write the method out separately, calling the three parameters we mentioned here: If x, resolve, reject * * is passed in the then execution, it will not be found, so it will be changed to asynchronous execution. Pass the return promise2 */ resolvePromise(promise2, x, resolve, reject) after the current then method executes. } catch (error) {// Call the reject method of the next then method, not this.reject reject(error); } }, 0) } else if (this.status === REJECTED) { setTimeout(() => { try { let y = failCallback(this.reason); reject(y); } catch (error) { reject(error); }}, 0)} else {/** * if the call is asynchronous, then the promise state is waiting for the call to succeed or fail, because we don't know whether it succeeded or failed. Then we need to store the success callback and the failure callback. */ / If the value of resolve fails or succeeds, then the resolve method will be called 2s later. // This. SuccessValue = successCallback; // this.failReason = failCallback; /** * THEN method is gradually called, which is a pity judgment or rejected judgment. If this is asynchronous, you need to store these asynchronous callback, and execute multiple THEN method calls successively after 2s. */ / try.. // This.successValue. push(successCallback); // this.failReason.push(failCallback); this.successValue.push(() => { setTimeout(() => { try { let x = successCallback(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); }}}, 0)); this.failReason.push(() => { setTimeout(() => { try { let y = failCallback(this.reason); reject(y); } catch (error) { reject(error); }}}, 0)); return; } function resolvePromise(resolvePromise, resolvePromise, resolvePromise, resolvePromise) reject) { console.log(promise2 === x); If (promise2 === x) {return Reject (new TypeError("Chaining cycle detected for promise #<Promise>")); } /** * If (x instanceof testPromise) {/** * if (x instanceof testPromise) {/** * Then Receiving successful and failed callback functions as arguments, */ / x. hen(value => resolve(value), reason => reject(reason)); Resolve (x)}} module.exports = testPromise;Copy the code
**index.js**
const testPromise = require ("./test-promise"); Let promise = new testPromise ((resolve, reject) => {setTimeout(() => {resolve(" success.....") ); }, 2000) // 6.1 throw new Error ("executor Error "); // resolve(" resolve "); // reject(" reject "); }) // 6.1 Test executor error // promise.then(value => {// console.log(value); / /}, a tiny = > {/ / console log (" capture "actuator" error > > > ", "reason); / /})/method / 6.2 then the success of the callback function abnormal / / promise. Then (value = > {/ / / / then method successfully abnormal in the callback is passed to the next / / throw new Error (" successCallback error"); / / / / / /}) in the second method then capture / /. Then (value = > {}, a tiny = > {. / / the console log (" capture the success callback 】 then method error > > > ", "reason); Then (value => {//},reason => {// throw new Error ("failCallback Error "); / / / / / /}) in the second method then capture / /. Then (value = > {}, a tiny = > {. / / the console log (" capture error method then failed callback 】 【 > > > ", "reason); Then (value => {throw new Error (" async Error "); // if (value => {throw new Error (" async Error "); },reason => {console.log(" catch [then method async callback] 111>>>", reason); }) // In the second then method catch. Then (value => {}, reason => {console.log(" catch [then method asynchronous callback] error >>>", reason); })Copy the code