Table of contents
No headings in the article.
Let's first build the general framework of the construction function
const PENDING ='pending'
const RESOLVED ='resolved'
const REJECTED ='rejected'
function MyPromise(fn) {
const that = this
that.state = PENDING
that.value = null
that.resolvedCallbacks = []
that.rejectedCallbacks = []
// To be improved resolve and reject functions
// To be perfected to execute the fn function
}
First of all, we created three constants to represent the state. Some frequently used values should be managed by constants, which is convenient for development and later maintenance.
The constant that is first created inside the function body, because the code may be executed asynchronously to obtain the correct this object
The state of Promise should be pending at the beginning
The value variable is used to save the value passed in resolve or reject resolvedCallbacks and rejectedCallbacks are used to save the callbacks in then, because the state may still be waiting when the Promise is executed. At this time, the callbacks in then should be saved for use when the state changes.
Next, let’s improve the resolve and reject functions and add them inside the body of the MyPromise function
function resolve(value) {
if (that.state === PENDING) {
that.state = RESOLVED
that.value = value
that.resolvedCallbacks.map(cb => cb(that.value))
}
}
function reject(value) {
if (that.state === PENDING) {
that.state = REJECTED
that.value = value
that.rejectedCallbacks.map(cb => cb(that.value))
}
}
The codes of these two functions are similar, so they are parsed together
First of all, both functions have to determine whether the current state is waiting, because the specification stipulates that only the waiting state can change the state
Change the current state to the corresponding state, and assign the passed value to value
Traverse the callback array and execute
After completing the above two functions, we should implement how to execute the function passed in the Promise
try {
fn(resolve, reject)
} catch (e) {
reject(e)
}
The implementation is very simple, execute the passed parameters and pass the previous two functions as parameters
It should be noted that an error may be encountered during the execution of the function, the error needs to be caught and the reject function is executed
Finally, let's implement the more complex then function
MyPromise.prototype.then = function(onFulfilled, onRejected) {
const that = this
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected =
typeof onRejected === 'function'
? onRejected
: r => {
throw r
}
if (that.state === PENDING) {
that.resolvedCallbacks.push(onFulfilled)
that.rejectedCallbacks.push(onRejected)
}
if (that.state === RESOLVED) {
onFulfilled(that.value)
}
if (that.state === REJECTED) {
onRejected(that.value)
}
}
-First determine whether the two parameters are function types, because these two parameters are optional parameters
- When the parameter is not a function type, a function needs to be created and assigned to the corresponding parameter, and transparent transmission is also realized,
The next step is a series of logic for judging the state. When the state is not a waiting state, the corresponding function is executed. If the state is in the waiting state, push the function in the callback function. For example, the following code will enter the logic of the waiting state
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 0)
}).then(value => {
console.log(value)
})