Write the source code
// State of the promise
const PENDING = 'pending'; / / wait for
const FULFILLED = 'fulfilled'; / / success
const REJECTED = 'rejected'; / / fail
class MyPromise {
constructor(executor) {
try {
execcutor(this.resolve, this,reject)
} catch(e) {
console.log(e); }}/ / promsie state
status = PENDING;
// Value after success
value = undefined;
// The cause of the failure
reason = undefined;
// The storage callback succeeded
successCallback = [];
// Storage failed callback
failCallback = [];
resolve = value= > {
// Stop the program from continuing if the current transition is not waiting
if (this.status ! == PENDING)return;
// Change the status to success
this. status = FULFILLED;
// Save the value after success
this.value = value;
// Determine if the successful callback exists
// We do not know the length of the successful callback array, so we use the while loop
while (this.successCallback.length) {
// Remove the first value with shift() and return the value
const callback = this.successCallback.shift();
The value returned is a function
callback();
}
}
reject = reason= > {
// Stop the program from continuing if the current transition is not waiting
if (this.status ! == PENDING)return;
// Change the status to failed
this. status = REJECTED;
// The cause of the save failure
this.reason = reason;
// Determine if the successful callback exists
// We do not know the length of the successful callback array, so we use the while loop
while (this.failCallback.length) {
// Remove the first value with shift() and return the value
const callback = this.failCallback.shift();
The value returned is a functioncallback(); }}/ / then method
then(successCallback, failCallback) {
// Parameters are optional
successCallback = successCallback ? successCallback : value= > value;
// Parameters are optional
failCallback = failCallback ? failCallback: reason= > { throw reason };
let promise2 = new MyPromise((resolve, reject) = > {
// Determine the status
if (this.status === FULFILLED) {
// Success status
setTimeout(() = > {
try {
let x = successCallback(this.value);
// The next step is to determine whether it is a normal value or a promise
resolvePromise(promise2, x, resolve, reject);
} catch(e) { reject(e); }})}else if (this.status === REJECTED) {
// Failed state
setTimeout(() = > {
try {
let x = failCallback(this.reason);
// The next step is to determine whether it is a normal value or a promise
resolvePromise(promise2, x, resolve, reject);
} catch(e) { reject(e); }})}else {
/ / wait for
// Store the success and failure callbacks
this.successCallback.push(() = > {
setTimeout(() = > {
try {
let x = successCallback(this.value);
// The next step is to determine whether it is a normal value or a promise
resolvePromise(promise2, x, resolve, reject);
} catch(e) { reject(e); }})})this.failCallback.push(() = > {
setTimeout(() = > {
try {
let x = failCallback(this.reason);
// The next step is to determine whether it is a normal value or a promise
resolvePromise(promise2, x, resolve, reject);
} catch(e) { reject(e); }})})return promsie2;
}
// Execute the finally method on failure or success
finally (callback) {
return this.then(value= > {
return MyPromise.resolve(callback()).then(() = > value)
},reason= > {
return MyPromise.resolve(callback()).then(() = > { throw reason })
});
}
// Error message catch method
catch (failCallback) {
return this.then(undefined, failCallback)
}
// Use the static all method
static all (array) {
let result = []; // Cache the return value of each async
let index = 0; // Record the execution value of arR
// Return a new promise
return new MyPromise((resolve, reject) = > {
function addData (key, value) {
result[key] = value;
index++;
// Record the value and the length of the array
if(index === array.length) { resolve(result); }}// Call the array one by one
for (let i = 0; i < array.length; i++) {
let current = array[i];
// Determine whether it is a normal value or a promise value
if (current instanceof MyPromise) {
/ / promise object
current.then(value= > addData(i, value), reason= > reject(reason))
}else {
/ / common valuesaddData(i, array[i]); }}})}// Use the static resolve method
static resolve (value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve= >resolve(value)); }}/ * * * *@param Promise2 A newly created promise@param X executes the return * of resolve or reject@param Resolve Resolve * of promise2@param Reject Reject */ of promise2
function resolvePromise(promise2, x, resolve, reject) {
if(promise2 === x) {
return reject(new TypeError('Promise returns itself in an infinite loop.'))}// Determine whether it is a normal value or a promise object
if(x instanceof MyPromise) {
/ / promise object
x.then(value= > resolve(value), reason= > reject(reason))
} else {
// The normal value returns the value directly
resolve(x)
}
}
module.exports = MyPromise;
Copy the code