.

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 allMyPromiseClass 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