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