从零手写Promise完整版

  • 随着前端技术的一直倒退,用户对界面的要求也在一直进步,当初的前端不再是之前的html+css, 而是html+css+js,然而想学好js首先要晓得js的外围在于异步,说到异步大部分人第一工夫会想到Promise
  • 那么接下来咱们就来学习一下Promise是如何实现的吧。
  • 首先咱们回顾一下Promise的根本应用
const p = new Promise((resolve,reject)=>{    resolve('返回胜利的值')    reject('返回失败的值')})p.then(value=>{    console.log(value) // 返回胜利的值})
  1. new Promise构造函数内的回调数是同步执行的
  2. then的回调函数,是异步执行的
  3. 调用resolve/reject后,状态已定,状态不能再扭转
  4. .then每次返回的都是新的Promise
  5. Promise能够嵌套

接着咱们从零开始来实现一下Promise

  • 先来实现明确一下根本的构造
(function(window){    // 定义MyPromise构造函数    function MyPromise(executor){        function resolve(value){        }        function reject(reason){        }        executor(resolve,reject)    }    // MyPromise原型链上存在then办法    MyPromise.prototype.then = function(onResolved,onRejected){    }    //MyPromise原型链上存在catch办法    MyPromise.prototype.catch = function(onRejected){    }    //MyPromise实例对象上存在resolve办法    MyPromise.resolve = function(value){    }    //MyPromise实例对象上存在reject办法    MyPromise.reject = function(reason){    }    //MyPromise实例对象上存在all办法    MyPromise.all = function(promises){    }    //MyPromise实例对象上存在race办法    MyPromise.race = function(promises){            }    window.MyPromise = MyPromise;})(window)
  • 明确来了根本的构造后,接下里咱们来看看MyPromise构造函数内须要做什么
  • 1.定义Promise的初始状态、初始值、寄存待执行异步函数的数组
(function(window){    const PENDDING = 'pendding';    const FULFILLED = 'fulfilled';    const REJECTED = 'rejected';    function MyPromise(executor){        const self = this;        self.status = PENDDING; //初始状态        self.data = undefined; // 初始值        self.callbacks = []; // 待执行异步回调函数的数组            function resolve(value){        }        function reject(reason){        }        executor(resolve,reject)    }    window.MyPromise = MyPromise;})(window)
    1. 依据Promise状态的不同,进行修,赋值,以及立刻执行异步回调
(function (window) {    const PENDDING = 'pendding';    const FULFILLED = 'fulfilled';    const REJECTED = 'rejected';    // 定义MyPromise    function MyPromise(executor) {        const self = this;        self.status = PENDDING;        self.data = undefined;        self.callbacks = [];        function resolve(value) {            self.status = FULFILLED;            self.data = value;            // 立刻执行异步回调函数            setTimeout(() => {                self.callbacks.forEach(callbacksObj => {                    callbacksObj.onResolved(value);                })            })        }        function reject(reason) {            self.status = REJECTED;            self.data = reason;            setTimeout(() => {                self.callbacks.forEach(callbacksObj => {                    callbacksObj.onRejected(reason);                })            })        }        executor(resolve, reject)    }    window.MyPromise = MyPromise;
    1. 别忘了Promise 的状态一旦扭转就不能再批改了,所以在resolve/reject函数内须要加一个判断
(function (window) {    const PENDDING = 'pendding';    const FULFILLED = 'fulfilled';    const REJECTED = 'rejected';    // 定义MyPromise    function MyPromise(executor) {        const self = this;        self.status = PENDDING;        self.data = undefined;        self.callbacks = [];        function resolve(value) {            if (self.status !== PENDDING) return;            self.status = FULFILLED;            self.data = value;            // 立刻执行异步回调函数            setTimeout(() => {                self.callbacks.forEach(callbacksObj => {                    callbacksObj.onResolved(value);                })            })        }        function reject(reason) {            if (self.status !== PENDDING) return;            self.status = REJECTED;            self.data = reason;            setTimeout(() => {                self.callbacks.forEach(callbacksObj => {                    callbacksObj.onRejected(reason);                })            })        }        executor(resolve, reject)    }    window.MyPromise = MyPromise;
    1. Promise原型链上的then办法,能够接管两个参数(且是回调函数),胜利/失败,并且每次返回的都是一个新的Promise
// MyPromise原型链上存在then办法MyPromise.prototype.then = function (onResolved, onRejected) {    const self = this;    return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象        // 首先判断以后状态        if (self.status === FULFILLED) {            /*                 1、返回的Promise的后果是由onResolved/onrejected决定的                2、返回的是Promise对象 (依据执后果决定Promise的返回后果)                3、返回的不是Promise对象 (该值就是Promise的返回后果)                4、抛出异样 异样的值为返回的后果            */            setTimeout(() => {                try {                    const result = onResolved(self.data);                    if (reject instanceof MyPromise) {                        result.then(value => {                            resolve(value);                        }, reason => {                            reject(reason);                        })                    } else {                        resolve(result);                    }                    } catch (error) {                    reject(error);                }            });            } else if (self.status === REJECTED) {            setTimeout(() => {                try {                    const result = onRejected(self.data);                    if (reject instanceof MyPromise) {                        result.then(value => {                            resolve(value);                        }, reason => {                            reject(reason);                        })                    } else {                        resolve(result);                    }                    } catch (error) {                    reject(error);                }            });            } else if (self.status === PENDDING) {            self.callbacks.push({                onResolved() {                    try {                        const result = onResolved(self.data);                        if (reject instanceof MyPromise) {                            result.then(value => {                                resolve(value);                            }, reason => {                                reject(reason);                            })                        } else {                            resolve(result);                        }                        } catch (error) {                        reject(error);                    }                },                onRejected() {                    try {                        const result = onRejected(self.data);                        if (reject instanceof MyPromise) {                            result.then(value => {                                resolve(value);                            }, reason => {                                reject(reason);                            })                        } else {                            resolve(result);                        }                        } catch (error) {                        reject(error);                    }                }            })        }    })}
  • 好的停一下,一步一步解说
    1. .then每次都返回一个新的Promise,所以在.then办法里是

> return new MyPromise((resolve,reject)){}

    1. 每一种状态都存在返回值,并且都能是一下三种状况
    2. 返回的是Promise对象
    3. 返回的不是Promise对象
    4. 抛出异样
    1. FULFILLED/REJECTED两种状态须要立刻执行异步函数
    1. PENDDING为什么没有立刻执行异步函数,因为当状态为PENDDING时就执行then,会先往待执行回调函数的数组(callbacks)内寄存这个回调,紧接着在回到Promise的执行其中执行resolve/reject,而下面也写过了,执行resolve/reject会去待执行回调函数的数组内遍历并赋值。

  • 好的持续,并且对下面反复的优化一下。
// MyPromise原型链上存在then办法    MyPromise.prototype.then = function (onResolved, onRejected) {        const self = this;        return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象            function handle(callback) {                /*                     1、返回的Promise的后果是由onResolved/onrejected决定的                    2、返回的是Promise对象 (依据执后果决定Promise的返回后果)                    3、返回的不是Promise对象 (该值就是Promise的返回后果)                    4、抛出异样 异样的值为返回的后果                */                try {                    const result = callback(self.data);                    if (reject instanceof MyPromise) {                        result.then(value => {                            resolve(value);                        }, reason => {                            reject(reason);                        })                    } else {                        resolve(result);                    }                } catch (error) {                    reject(error);                }            }            // 首先判断以后状态            if (self.status === FULFILLED) {                setTimeout(() => {                    thandle(onResolved)                });            } else if (self.status === REJECTED) {                setTimeout(() => {                    thandle(onRejected)                });            } else if (self.status === PENDDING) {                self.callbacks.push({                    onResolved() {                        handle(onResolved)                    },                    onRejected() {                        handle(onRejected)                    }                })            }        })    }
    1. 避免不穿胜利或者失败的回调函数,给胜利和失败都给一个默认回调函数
MyPromise.prototype.then = function (onResolved, onRejected) {        const self = this;        // 定义默认回调        onResolved = typeof onResolved === "function" ? onResolved : value => value;        onRejected = typeof onRejected === "function" ? onRejected : reason => {throw reason};        return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象            function handle(callback) {                /*                     1、返回的Promise的后果是由onResolved/onrejected决定的                    2、返回的是Promise对象 (依据执后果决定Promise的返回后果)                    3、返回的不是Promise对象 (该值就是Promise的返回后果)                    4、抛出异样 异样的值为返回的后果                */                try {                    const result = callback(self.data);                    if (reject instanceof MyPromise) {                        result.then(value => {                            resolve(value);                        }, reason => {                            reject(reason);                        })                    } else {                        resolve(result);                    }                } catch (error) {                    reject(error);                }            }            // 首先判断以后状态            if (self.status === FULFILLED) {                setTimeout(() => {                    thandle(onResolved)                });            } else if (self.status === REJECTED) {                setTimeout(() => {                    thandle(onRejected)                });            } else if (self.status === PENDDING) {                self.callbacks.push({                    onResolved() {                        handle(onResolved)                    },                    onRejected() {                        handle(onRejected)                    }                })            }        })    }
    1. 接着咱们看看catch,其实就是
Promise.prototype.then(undefined,rejected)
  • 或者
Promise.prototype.then(null,rejected)
//MyPromise原型链上存在catch办法  MyPromise.prototype.catch = function (onRejected) {    return this.then(null, onRejected);  }
  • 7、接下来实现一下 Promise.resolve/Promise.reject
/MyPromise实例对象上存在resolve办法MyPromise.resolve = function (value) {    if (value instanceof MyPromise) return value;    return new MyPromise(resolve => resolve(value))             // 返回一个resolved状态的Promise对象}//MyPromise实例对象上存在reject办法MyPromise.reject = function (reason) {    return new MyPromise((resolve,reject) => reject(reason));  // 返回一个reject状态Promise对象}
    1. 接下来实现一下Promise.all/Promise.race
//MyPromise实例对象上存在all办法MyPromise.all = function (promises) {    let promisesCount = 0    let values = new Array(promises.length);    return new MyPromise((resolve,reject)=>{        promises.forEach((promise,index)=>{            promise.then(value => {                promisesCount++;                values[index] = value;                if (promisesCount === promises.length){                    resolve(values);                }            },reason => {                reject(reason);            })        })    })}
  • 好的,咱们来看看Promise.all实现的思路

      1. Promise.all 传入的是一个数组
      1. Promise.all返回的是一个数组
      1. Promise.all传入的数组中,每个Promise对象必须都正确能力返回正确的后果数组
      1. Promise.all传入的数组中任意一个对象返回错的后果,都会返回谬误的后果
  • 好的,其实咱们还少一个步骤就是Promise.all传入的数组的参数能够不是Promise的实例, 所以数组参数如果不是Promise实例,先调用Promise.resolve
//MyPromise实例对象上存在all办法MyPromise.all = function (promises) {    let promisesCount = 0    let values = new Array(promises.length);    return new MyPromise((resolve, reject) => {      promises.forEach((promise, index) => {        MyPromise.resolve(promise).then(value => {          promisesCount++;          values[index] = value;          if (promisesCount === promises.length) {            resolve(values);          }        }, reason => {          reject(reason);        })      })    })}
  • Promise.race实现
//MyPromise实例对象上存在race办法  MyPromise.race = function (promises) {    return new MyPromise((resolve, reject) => {      promises.forEach(promise => {        MyPromise.resolve(promise).then(value => {          resolve(value);        }, reason => {          reject(reason)        })      })    })  }
    • 好的,解释一下,

        1. Promise.race传入的也是一个数组
        1. 传入的Promise执行内容雷同的状况下,Promise.race返回的后果为数组中的第一个值
        1. 若传入的Promise执行内容不统一,有先后辨别,则后果为执行的最快的一个
    • 至此从零手写一个Promise实现了,其中包含
    Promise.prototype.then

    Promise.prototype.catch

    Promise.resolve

    Promise.reject

    Promise.all

    Promise.race

    (function (window) {  const PENDDING = 'pendding';  const FULFILLED = 'fulfilled';  const REJECTED = 'rejected';  // 定义MyPromise  function MyPromise(executor) {    const self = this;    self.status = PENDDING;    self.data = undefined;    self.callbacks = [];    function resolve(value) {      if (self.status !== PENDDING) return;      self.status = FULFILLED;      self.data = value;      // 立刻执行异步回调函数      setTimeout(() => {        self.callbacks.forEach(callbacksObj => {          callbacksObj.onResolved(value);        })      })    }    function reject(reason) {      if (self.status !== PENDDING) return;      self.status = REJECTED;      self.data = reason;      setTimeout(() => {        self.callbacks.forEach(callbacksObj => {          callbacksObj.onRejected(reason);        })      })    }    try{      executor(resolve, reject)    }catch(error){      reject(error)    }      }  // MyPromise原型链上存在then办法  MyPromise.prototype.then = function (onResolved, onRejected) {    const self = this;    // 定义默认回调    onResolved = typeof onResolved === "function" ? onResolved : value => value;    onRejected = typeof onRejected === "function" ? onRejected : reason => {      throw reason    };    return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象      function handle(callback) {        /*             1、返回的Promise的后果是由onResolved/onrejected决定的            2、返回的是Promise对象 (依据执后果决定Promise的返回后果)            3、返回的不是Promise对象 (该值就是Promise的返回后果)            4、抛出异样 异样的值为返回的后果        */        try {          const result = callback(self.data);          if (reject instanceof MyPromise) {            result.then(value => {              resolve(value);            }, reason => {              reject(reason);            })          } else {            resolve(result);          }        } catch (error) {          reject(error);        }      }      // 首先判断以后状态      if (self.status === FULFILLED) {        setTimeout(() => {          handle(onResolved)        });      } else if (self.status === REJECTED) {        setTimeout(() => {          handle(onRejected)        });      } else if (self.status === PENDDING) {        self.callbacks.push({          onResolved() {            handle(onResolved)          },          onRejected() {            handle(onRejected)          }        })      }    })  }  //MyPromise原型链上存在catch办法  MyPromise.prototype.catch = function (onRejected) {    return this.then(null, onRejected);  }  //MyPromise实例对象上存在resolve办法  MyPromise.resolve = function (value) {    if (value instanceof MyPromise) return value;    return new MyPromise(resolve => resolve(value)) // 返回一个resolved状态的Promise对象  }  //MyPromise实例对象上存在reject办法  MyPromise.reject = function (reason) {    return new MyPromise((resolve, reject) => reject(reason)); // 返回一个reject状态Promise对象  }  //MyPromise实例对象上存在all办法  MyPromise.all = function (promises) {    let promisesCount = 0    let values = new Array(promises.length);    return new MyPromise((resolve, reject) => {      promises.forEach((promise, index) => {        MyPromise.resolve(promise).then(value => {          promisesCount++;          values[index] = value;          if (promisesCount === promises.length) {            resolve(values);          }        }, reason => {          reject(reason);        })      })    })  }  //MyPromise实例对象上存在race办法  MyPromise.race = function (promises) {    return new MyPromise((resolve, reject) => {      promises.forEach(promise => {        MyPromise.resolve(promise).then(value => {          resolve(value);        }, reason => {          reject(reason)        })      })    })  }  window.MyPromise = MyPromise;})(window)
    • 最初咱们用类(class)的形式实现一下
    (function (window) {    const PENDDING = 'pendding';    const FULFILLED = 'fulfilled';    const REJECTED = 'rejected';    // 定义MyPromise    class MyPromise {        constructor(executor) {            const self = this;            self.status = PENDDING;            self.data = undefined;            self.callbacks = [];            function resolve(value) {                if (self.status !== PENDDING) return;                self.status = FULFILLED;                self.data = value;                // 立刻执行异步回调函数                setTimeout(() => {                    self.callbacks.forEach(callbacksObj => {                        callbacksObj.onResolved(value);                    })                })            }            function reject(reason) {                if (self.status !== PENDDING) return;                self.status = REJECTED;                self.data = reason;                setTimeout(() => {                    self.callbacks.forEach(callbacksObj => {                        callbacksObj.onRejected(reason);                    })                })            }            executor(resolve, reject)        }        // MyPromise原型链上存在then办法        then(onResolved, onRejected) {            const self = this;            // 定义默认回调            onResolved = typeof onResolved === "function" ? onResolved : value => value;            onRejected = typeof onRejected === "function" ? onRejected : reason => {                throw reason            };            return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象                function handle(callback) {                    /*                         1、返回的Promise的后果是由onResolved/onrejected决定的                        2、返回的是Promise对象 (依据执后果决定Promise的返回后果)                        3、返回的不是Promise对象 (该值就是Promise的返回后果)                        4、抛出异样 异样的值为返回的后果                    */                    try {                        const result = callback(self.data);                        if (reject instanceof MyPromise) {                            result.then(value => {                                resolve(value);                            }, reason => {                                reject(reason);                            })                        } else {                            resolve(result);                        }                    } catch (error) {                        reject(error);                    }                }                // 首先判断以后状态                if (self.status === FULFILLED) {                    setTimeout(() => {                        handle(onResolved)                    });                } else if (self.status === REJECTED) {                    setTimeout(() => {                        handle(onRejected)                    });                } else if (self.status === PENDDING) {                    self.callbacks.push({                        onResolved() {                            handle(onResolved)                        },                        onRejected() {                            handle(onRejected)                        }                    })                }            })        }        //MyPromise原型链上存在catch办法        catch (onRejected) {            return this.then(null, onRejected);        }        //MyPromise实例对象上存在resolve办法        static resolve(value) {            if (value instanceof MyPromise) return value;            return new MyPromise(resolve => resolve(value)) // 返回一个resolved状态的Promise对象        }        //MyPromise实例对象上存在reject办法        static reject(reason) {            return new MyPromise((resolve, reject) => reject(reason)); // 返回一个reject状态Promise对象        }        //MyPromise实例对象上存在all办法        static all(promises) {            let promisesCount = 0            let values = new Array(promises.length);            return new MyPromise((resolve, reject) => {                promises.forEach((promise, index) => {                    MyPromise.resolve(promise).then(value => {                        promisesCount++;                        values[index] = value;                        if (promisesCount === promises.length) {                            resolve(values);                        }                    }, reason => {                        reject(reason);                    })                })            })        }        //MyPromise实例对象上存在race办法        static race(promises) {            return new MyPromise((resolve, reject) => {                promises.forEach(promise => {                    MyPromise.resolve(promise).then(value => {                        resolve(value);                    }, reason => {                        reject(reason)                    })                })            })        }    }    window.MyPromise = MyPromise;})(window)
    • 从零手写Promise说难也不难,然而还是花了不少工夫的,心愿可能帮忙到像我一样想学好js,想学好Promise的敌人,一起加油吧。

    最初

    • 如果你想退出特皮技术团队,有人领导你学习,晋升本人,能够公众号分割我
    • 感觉对你有帮忙,能够点个在看,转发一下,关注咱们公众号:【前端巅峰