Author: @gauseen
The Promises/A + specification can be Here See
promise has three states, pending, fulfilled and rejected
-
promise in pending state
- You can switch to fulfilled or rejected state
-
promise in fulfilled state
- Can't switch to other states
- Must have a value that cannot be changed
-
promise in rejected state
- Can't switch to other states
- There must be a reason value that cannot be changed
// Three states of promise const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' // MyPromise constructor function MyPromise (fn) { // Initialization state this.state = PENDING this.result = void 0 this.handlerQueue = [] let resolve = (value) => { transitionState(this, FULFILLED, value) } let reject = (reason) => { transitionState(this, REJECTED, reason) } // Call Promise constructor callback try { fn(resolve, reject) } catch (error) { reject(error) } }
The state migration method, which calls resolution in FN (resolution, reject), needs to change the promise state:
pending --> fulfilled
pending --> rejected
function transitionState (promise, state, result) { if (promise.state !== PENDING) return promise.state = state promise.result = result // Here's a pit first. }
then
The method returns a new onePromise
Example (Note: Not the original one)Promise
Only in this way can we make continuous chain calls and change state in turnMyPromise.prototype.then = function (onFulfilled, onRejected) { return new MyPromise((resolve, reject) => { let handler = { onFulfilled, onRejected, resolve, reject } // If the current state is pending, place it in the handlerQueue queue and wait for the resolve or reject method to change its state // Otherwise, call directly the resolve or reject callback function in the then method if (this.state ==== PENDING) { this.handlerQueue.push(handler) } else { dispatchHandler(handler, this.state, this.result) } }) }
const isFunction = arg => typeof arg === 'function' function dispatchHandler (handler, state, result) { let { onFulfilled, onRejected, resolve, reject } = handler if (state === FULFILLED) { let finalValue = isFunction(onFulfilled) ? onFulfilled(result) : result resolve(finalValue) } else if (state === REJECTED) { let finalReason = isFunction(onRejected) ? onRejected(result) : result reject(finalReason) } }
The above code only supports synchronous invocation of Promise callback function parameters resolve and reject, as follows:
// Support let myPromise = new MyPromise((resolve, reject) => { // resolve synchronous call resolve('Synchronous invocation value') }) myPromise.then((value) => { console.log('value: ', value) }, (reason) => { console.log('reason: ', reason) })
However, the use of asynchronous calls is not supported, as shown in the following example code:
// Temporary support let myPromise = new MyPromise((resolve, reject) => { // resolve asynchronous call setTimeout(() => { resolve('Asynchronous call value') }) }) myPromise.then((value) => { console.log('value: ', value) }, (reason) => { console.log('reason: ', reason) })
Asynchronous call to resolve or reject is not supported because of the following code fragments in the then method:
// When the solution is called asynchronously and the then method executes, the promise state is pending. // So the N callback functions onFulfilled and onRejected are not called in the handlerQueue queue if (this.state ==== PENDING) { this.handlerQueue.push(handler) } else { // ... }
To support asynchronous invocation of resolve and reject, the state migration method transitionState is modified as follows:
function transitionState (promise, state, result) { if (promise.state !== PENDING) return promise.state = state promise.result = result // New Code Start promise.handlerQueue.forEach(handler => { dispatchHandler(handler, state, result) }) // End of new code }
Because the catch method is an alias for. then(null, onRejected), the implementation of the catch code is as follows:
MyPromise.prototype.catch = function (onRejected) { return this.then(null, onRejected) }
As mentioned above, promise is implemented simply to support chain call of then and catch
Welcome to Pay Attention to Non-Advertising Articles Public Number: Front-end