Implement promises manually
Please refer to the official documentCopy the code
state
Promise has three states, which are:
- Pending Initial state
- State of success
- Rejected State
Only in the pending state, a Promise can be changed to other states. When the state is changed, it cannot be changed to other states.
const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; Function MyPromise(excutor){function MyPromise(excutor){this.status = pending; }Copy the code
A function that executes immediately
The Promise receives an immediate function (executor: Excutor) that accepts two callback functions, resolve(success callback) and Reject (failure callback).
- The state will be fulfilled and the value of success will be assigned
- Reject Indicates the reject callback, changing the status to Rejected and assigning the failure reason
const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; Function MyPromise(excutor){function MyPromise(excutor){this.status = pending; // This. Value = undefined; // This. Reason = undefined; Ledcallback = []; ledcallback = []; rejectedCallback = []; const resolve = (value) => { if (this.status === PENDING) { this.status = FULFILLED; this.value = value; } } const reject = (reason) => { if (this.status === PENDING) { this.status = REJECTED; this.reason = reason; } } try{ excutor(resolve, reject) }catch(err){ throw err; }}Copy the code
Then method
new Promise((...) = > {... }).then(res => {}, err => {})Copy the code
Then handles successful or failed state callbacks and returns a new promise based on the value of the callback
- Receives two callback functions
- OnResolve success handler function
- OnReject Failure handler function
- Return a new Promise
- When the state is fulfilled, onResolve will be executed and a new Promise will be returned. The result of the new Promise will be determined by onResolve
- When the state is Rejected, onReject is executed and a new Promise is returned, the result of which is determined by onReject
- When the state is pending, the onResolve and onReject functions are saved and executed after the state changes.
- Since two callback functions need to be stored when the state is pending, two new arrays need to be created to store them.
Mypromise.prototype. Then = function(onResolve, onReject){ Use the default callback onResolve = typeof onResolve === 'undefined'? onResolve:value => value; onReject = typeof onReject === 'undefined'? OnReject :reason => {throw reason} return new MyPromise((resolve, resolve) This is a big pity if(this. Status === big pity){setTimeout(() => {try{// Execute onResolve const result => onResolve(this.value); // if onResolve returns a Promise, If (result instanceof MyPromise){result.then(resolve, Reject)}else{reject(result)}catch(error){reject(error)}})} If (this.status === reject){try{const result = onReject(this.reason); if(this.status === reject){try{const result = onReject(this.reason); if(result instanceof MyPromise){ result.then(resolve, reject) }else{ resolve(result) } }catch(error){ reject(error) } } }) }Copy the code
Optimize the above method to implement the pending method.
MyPromise.prototype.then = function(onResolve, onReject){ return new MyPromise((resolve, Reject) => {function handleFunc(func, value){try {const result = func(value); If (result instanceof MyPromise) {result.then(resolve, reject); } else { resolve(result) } } catch (err) { reject(err) } } if (this.status === FULFILLED) { setTimeout(() => { handle(onResolve, this.value) }) } if (this.status === REJECTED) { setTimeout(() => { handle(onReject, This.reason)})} // State is pending, To save the callback function to set the previously defined function if (this. The status = = = PENDING) {/ / save the fulfilledCallback enclosing fulfilledCallback. Push (value = > { Handle (onResolve, value)}) / / save the rejectedCallback enclosing rejectedCallback. Push (" reason = > {handle (onReject, reason) }) } }) }Copy the code
When the state is changed from pending to another state, the then callback function will not be executed. Therefore, modify the two callback functions of excutor, resolve and reject
Const resolve = (value) => {if (this.status === PENDING) {this.status = FULFILLED; this.value = value; SetTimeout () = > {/ / state changes after carry out then the callback function enclosing fulfilledCallback. ForEach (fn = > fn (value))})}} const reject = (reason) => { if (this.status === PENDING) { this.status = REJECTED; this.reason = reason; setTimeout(() => { this.rejectedCallback.forEach(fn => fn(reason)) }) } } try { excutor(resolve, reject); } catch (err) { throw err; }}Copy the code
Reject method
MyPromise.reject(reason)
Copy the code
Return a failed Promise for a given reason
MyPromise.reject = function(reason){
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
Copy the code
Resolve method
MyPromise.resolve(value);
Copy the code
Return a parsed Promise, or if the value is another Promise, that Promise will be returned directly.
- Return a new Promise, note that the state of the Promise can be either successful or failed.
- If it is a normal value, the status is resolved to success and the value is returned
- If the value is a Promise, the state will be determined by that Promise
Mypromise.resolve = function(value){return new MyPromise((resolve, reject) => {// if value is a Promise, If (value instanceof MyPromise){value. Then (resolve, reject)}else{resolve(value)}})}Copy the code
All methods
MyPromise.all([promise1, promise2]).then(([p1, p2]) => {}, reason => {})
Copy the code
After all promises succeed or one fails, return an array of successful results for all promises or a reason for the failure.
- Receive an array, which can be a promise or a normal value
- Return a new promise
- One failure and promise.all would be a complete failure. And returns the promise of a failed state
- In the success state, as many successful results are returned as many promises are saved, and the locations of the results are the same as where the Promise was passed in
MyPromise.all = function (promises) { let results = new Array(promises.length); let fulfilledCount = 0; Return new MyPromise((resolve, reject) => {// If the promise array is empty, If (promises. Length === 0) {resolve([])} // if (promises. Length === 0) {resolve([])} index) { fulfilledCount++; results[index] = value; if (fulfilledCount === promises.length) { resolve(results) } } promises.forEach((promise, If (promise instanceof MyPromise) {promise.then(res => {ledHandle(res, Index)}, reason => {reject(reason)})} else {ledHandle(res, index)}})})}Copy the code
Race method
MyPromise.race([promise.resolve(1), promise.reject(2)]).then(res=>{},reason=>{})
Copy the code
This method returns a promise, receives an array, and if one of the promises in the array succeeds or fails, the state of the returned promise determines whether it succeeds or fails.
Note: Only the first successful or failed promise or value is taken, others are ignored.
MyPromise.race = function (promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
if (promise instanceof MyPromise) {
promise.then(resolve, reject)
} else {
resolve(promise)
}
})
})
}
Copy the code