.
I wrote a promise with the course before, and the teacher asked us to learn the knowledge related to promise in this internship training. I thought that I had covered some basic law last time, but I only had some impression of the principle, so I decided to write it again and see if I could get new experience after two times. Hopefully we can get the promise principle straight.
write
First of allMyPromise
Class construction, and basic asynchronous functionality. New MyPromise(resolve, reject).then(value => {}, reason => {}), features and methods such as chained calls, promise.all are developed later.
/* The first three states of promise are: This is a big pity, which is a big pity, and the change of the failed state is irreversible. That is, there are only two forms, namely, PENDING => FULFILLED, PENDING => FULFILLED */
const PENDING = 'PENDING'
const FULFILLED = 'RESOLVE'
const REJECTED = 'REJECT'
/* Construct a MyPromise class, using ES6 class notation */
class MyPromise {
/* The executor received by the constructor function is a function that executes */ immediately upon instantiation of MyPromise
constructor(executor) {
try {
executor(this.resolve.bind(this), this.reject.bind(this))}catch(e) {
this.reject(e)
}
}
/* The initial state is PENDING*/
status = PENDING
value = undefined // The promise value, obtained in the resolve method
reason = undefined // The failure reason is obtained in reject
successCallback = null // Success callback function
failCallback = null // Failed callback function
/* The successful execution of the function will receive the successful execution of the value*/
resolve(value) {
if(this.status ! == PENDING)return // If not PENDING, this function should not be executed
this.status = FULFILLED // Set the state to complete
this.value = value // Save the value passed in
this.successCallback && this.successCallback(this.value) // The callback was successfully executed
}
/* Similar to resolve */
reject(reason) {
if(this.status ! == PENDING)return
this.status = REJECTED
this.reason = reason
this.failCallback && this.failCallback(this.reason)
}
/* A callback to a state change that can be followed up on a value generated after promise */
then(successCallback, failCallback) {
this.successCallback = successCallback ? successCallback: value= > value
this.failCallback = failCallback ? failCallback: reason= > { throw reason }
/* Determine which callback function to execute by state */
switch(this.status) {
case FULFILLED: {
this.successCallback(this.value)
}
case REJECTED: {
this.failCallback(this.reason)
}
}
}
}
Copy the code
Advanced version: The promsie for this basic functionality is then improved to accept multiple callback functions that can be chain-called
const PENDING = 'PENDING'
const FULFILLED = 'RESOLVE'
const REJECTED = 'REJECT'
class MyPromise {
constructor(executor) {
try {
executor(this.resolve.bind(this), this.reject.bind(this))}catch(e) {
this.reject(e)
}
}
status = PENDING
value = undefined
reason = undefined
successCallbackQueue = [] // Change a single callback function to an array of callbacks, so that multiple callbacks can be received
failCallbackQueue = []
resolve(value) {
if(this.status ! == PENDING)return
this.status = FULFILLED
this.value = value
/* Retrieves the callback function from the header of the success callback array and executes */
while(this.successCallbackQueue.length > 0) {
this.successCallbackQueue.shift()(this.value)
}
}
reject(reason) {
if(this.status ! == PENDING)return
this.status = REJECTED
this.reason = reason
/* Retrieves the callback function from the head of the failed callback array and executes */
while(this.successCallbackQueue.length > 0) {
this.failCallbackQueue.shift()(this.reason)
}
}
/* To make a chained call, the then method must return a MyPromise. The value and reason received by the new MyPromise are the values returned by the first MyPromise resolve or Reject callback */
then(successCallback,failCallback){
successCallback = successCallback ? successCallback:value= > value
failCallback = failCallback ? failCallback:reason= > {throw reason}
// Determine which callback to execute based on the status
let newPromise = new MyPromise((resolve,reject) = >{
switch(this.status) {
case FULFILLED: {
// execute asynchronously to get newPromise
setTimeout(() = > {
let x = successCallback(this.value)
this.handlePromise(x,resolve,reject) Pass the value of the successful callback to the next promise's THEN
},0)}break
case REJECTED: {
// execute asynchronously to get newPromise
setTimeout(() = > {
let x = failCallback(this.reason)
this.handlePromise(x,resolve,reject)
},0)}break
case PENDING: {
// Store success and failure callbacks
this.successCallbackQueue.push(() = > {
setTimeout(() = > {
let x = successCallback(this.value)
this.handlePromise(x,resolve,reject)
},0)})this.failCallbackQueue.push(() = > {
setTimeout(() = > {
let x = failCallback(this.reason)
this.handlePromise(x,resolve,reject)
},0)})}break}})return newPromise
}
/* Callback returns the value handler */
handlePromise(x, resolve, reject) {
if(x instanceof MyPromise) { // If x is a MyPromise object, resolve or reject is the value of the then method
x.then(value= > resolve(value),reason= > reject(reason))
} else {
resolve(x) // If normal, resolve}}}Copy the code
Ultimate: Now that I’ve completed the basic promise functionality, I’m ready to add some static methods to my promsie class that will make my promises feel more comfortable. I added promise. all, promise. race, promise. finall and other methods
/* Promise.all, accept an array, reject all Promise states, reject all Promise states, reject all Promise states, reject all Promise states */
static all(promiseArray) {
return new MyPromise((resolve, reject) = > {
let count = promiseArray.length
const res = []
while(promiseArray.length > 0) {
const x = promiseArray.shift()
/* If array element x is myPromise, its then method is called and the result is pushed into an array */
if(x instanceof MyPromise) {
x.then(value= > {
res.push(value)
count--
if(count === 0) resolve(res)
}, reason= > {
reject(reason)
})
} else {
Resolve: myPromise.resolve: mypromise.resolve: mypromise.resolve
res.push(x)
count--
if(count === 0) resolve(res)
}
}
})
}
/* promise. reca, like all, accepts an array of promises, but returns resolve or reject when the first Promise state changes
static race(promiseArray) {
return new MyPromise((resolve, reject) = > {
const res = []
while(promiseArray.length > 0) {
const x = promiseArray.shift()
if(x instanceof MyPromise) {
x.then(value= > {
resolve(value)
}, reason= > {
reject(reason)
})
}
}
})
}
static resolve(n) { // Return a resolve promise
if(n instanceof MyPromise) return n
return new MyPromise(resolve= > resolve(n))
}
/*finally */
finally(callback){ The finally function is executed in either resolve or reject
return this.then(value= > {
// Wait for callback to complete and return value
return MyPromise.resolve(callback()).then(() = > value)
},reason= > {
return MyPromise.resolve(callback()).then(() = > reason)
})
}
Copy the code