Write at the beginning: if the big guys see there is a mistake please correct, if the cute new to the ditch, you climb out of the good (manual funny)
After optimizing the asynchronous code logic in the Promise implementation, the next step is to optimize the THEN methods
The then method can be called multiple times in a Promise.
In the case of synchronous execution, the current state of each Promise is immediately known as success or failure, so the code here is fine, but it would be if the Promise was executed asynchronously. (See below)
The reason is that only one value is defined when successful and failed callbacks are defined, not taking into account the case that the THEN method is called multiple times in async, so the successful and failed callbacks should be defined as an array that can hold multiple values.
successCallback = [];
failCallback = [];
Copy the code
So the callback store in the then method also changes:
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
Copy the code
By now, multiple callback functions have been stored in the success/failure callback array. When the status changes to success/failure, each item in the callback array should be called in turn, so resolve/ Reject should be changed
resolve = value => { if (this.status ! == PENDING) return; this.status = FULFILLED; this.value = value; While (enclosing successCallback. Length) {/ / an array of the first item should be performed, and an array of the first is the need to the callback function so you can direct call this. SuccessCallback. The shift () (enclosing value); } } reject = value => { if (this.status ! == PENDING) return; this.status = REJECTED; this.reason = reason; While (this.failcallback.length) {resolve this.failcallback.shift ()(this.reason); }}Copy the code
The then method can be called multiple times in a Promise. The then method can be called multiple times in a Promise.
promise.then().then().then()
Copy the code
The call value obtained by the later THEN method is the return value returned by the previous THEN method.
So the next step is to implement a chain call to the THEN method.
Let’s start with the then method:
- The then method is in the Promise
- Since the THEN method can be called chained, the return value of the THEN method is a Promise object
// Since the then method returns a Promise object, So let's create a Promise object that returns then(successCallback, failCallback) { let thenPromise = new myPromise(() => { if (this.status === FULFILLED) { successCallback(this.value); } else if (this.status === REJECTED) { failCallback(this.reason); }}); return thenPromise; };Copy the code
The then method returns a Promise object that can be used for the next call to the THEN. Now you need to think about how the next THEN method will get the Promise object returned by the previous THEN.
Then (successCallback, failCallback) {let thenPromise = new myPromise(resolve, reject) => { This is very depressing. This is very depressing. If (this.status === big) {// This x is the return value of the successful callback. resolve(x); } else if (this.status === REJECTED) { let x = failCallback(this.reason); reject(x); }}); return thenPromise; };Copy the code
The then method can then return a Promise object. But what if the return value is a Promise object? Promise in a Promise return? Give or take another word, so write the estimate is not far from being killed…)
So the next thing you need to do is determine whether x is a normal value or a Promise object; If the value is normal, resolve is used. If it is a Promise object, use resolve or reject based on the result returned by the Promise object.
// argParsing(x, resolve, reject) {// argParsing(x, resolve, reject) {// argParsing(x, resolve, reject) {// argParsing(x, resolve, reject); If (x instanceof myPromise) {x. tran (value => {resolve(value); }, reason => { reject(reason); }); // This stack can also be shortened to x. Chen (resolve, reject); } else { resolve(x); }}Copy the code
We’re done checking that x is a Promise object. Now let’s call it
then(successCallback, failCallback) {
let thenPromise = new myPromise((resolve, reject) => {
if (this.status === FULFILLED) {
let x = successCallback(this.value);
argParsing(x, resolve, reject);
} else if (this.status === REJECTED) {
let x = failCallback(this.reason);
argParsing(x, resolve, reject);
} else {
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
})
return thenPromise;
}
Copy the code
This completes the chain call to the THEN method.
So the Promise code implemented so far should look like this:
const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected' class myPromise { constructor(executor) { executor(this.resolve, this.reject) } status = PENDING; value = undefined; reason = undefined; successCallback = []; failCallback = []; resolve = (value) => { if (this.status ! == PENDING) return; this.status = FULFILLED; this.value = value; while (this.successCallback.length) { this.successCallback.shift()(this.value); } } reject = (reason) => { if (this.status ! == PENDING) return; this.status = REJECTED; this.reason = reason; while (this.failCallback.length) { this.failCallback.shift()(this.reason); } } then(successCallback, failCallback) { let thenPromise = new myPromise((resolve, reject) => { if (this.status === FULFILLED) { let x = successCallback(this.value); argParsing(x, resolve, reject); } else if (this.status === REJECTED) { let x = failCallback(this.reason); argParsing(x, resolve, reject); } else { this.successCallback.push(successCallback); this.failCallback.push(failCallback); } }) return thenPromise; } } function argParsing(x, resolve, reject) { if (x instanceof myPromise) { x.then(resolve, reject); } else { resolve(x); }}Copy the code