1、 promise是个构造函数;
promise的构造函数内部要声明一个表示状态的属性state(默认pending)和结果result;
promise支持异步调用,设置一个callbacks保存回调函数,且支持链式调用所以数据类型为数组;
接收的参数是个函数(有resolve和reject两个参数),在构造函数中定义resolve和reject两个方法
2、 构造函数中的resolve方法,promise的状态改变只有一次,所以state不是pending直接return;
之后state改为fulfilled并为result赋值(resolve的行参data);
执行回调函数,因为promise的链式调用,遍历执行callbacks中接收的onResolve方法;
3、 reject方法与resolve类似,判断pending—>修改state为reject—>给result赋值—>遍历执行回调
4、 执行构造函数传入的参数函数(executor),把resolve和reject方法传入, executor(resolve, reject)
promise的状态可以被throw方法改变,所以使用try catch执行,try executor catch则reject();
5、 promise实例有then和catch方法,所以写在promise的prototype上;
catch相当于then方法不传第一个参数,所以catch可以直接返回promise.then(undefined, onRejected)
6、 then方法的处理,then要写在原型上;
then接收两个函数作为参数,onResolve和onReject,注意空值处理,没传参数或类型不是function是给默认方法,onResolve默认将value向下传递(链式调用),onReject默认throw reason
then返回的是promise对象,所以return new promise
在返回的promise对象中处理各种逻辑,实例的state为fulfill时调用onResolved,reject时调用onRejected,pending时向callbacks数组中push存有两个回调函数的对象为promise构造函数中执行时遍历回调使用
then返回的是一个promise对象,默认resolve状态,且promise有错误穿透所以对onResolved和onRejected都进行try catch执行,并判断执行结果是否为promise实例,是则resolve,否则reject;
上述对onResolved和onRejected的处理可以进行封装,封装成一个callback方法。接收参数为要执行的方法;
7、 注意then中的回调函数是异步执行的 所以使用setTimeout包裹resolve和reject方法,promise构造函数中的callbacks回调事件数组同理
8、 实现promise的其它方法resolve、reject、all、race;按照特性写就ok;方法不在实例上调用所以写在promise函数上而不是promise原型上
resolve return一个promise对象,传入普通类型 return 结果为resolve,传入promise return的结果与传入的promise运行结果一致
reject 返回一个promise对象 无论如何都是reject
all 接收一个promise数组,所有resolve返回resolve,结果为数组,遍历调用传入的数组的每一个promise对象的then方法,resolve则计数+存结果,知道数和传入的数组长度相等 resolve(arr),reject则reject(r);
race 返回第一个执行完毕的,所以return一个promise对象 遍历执行传入数组的promise对象的then方法,resolve便resolve(); reject则reject();
9、 写完之后可以选择使用class封装Promise,声明一个class ,constructor为构造函数,然后有then和catch方法,将resolve reject all race等方法写成静态属性 前面加static
// 声明结构 promise 是个构造函数,接收一个函数做为参数function _Promise (executor) {// 声明返回状态和返回结果this.PromiseState = 'pending'; // 默认pending状态this.PromiseResult = null;this.callbacks = []; // 保存回调函数,promise可以多次回调 所以选择使用数组const _this = this; // 为了在函数中使用this// 声明resolve 和 reject函数, 接收data作为返回结果function resolve (data) {// resolve和reject只能执行一次,状态只能改变一次,不是pending状态便返回if (_this.PromiseState !== 'pending') {return;}_this.PromiseState = 'fulfilled'; // 修改状态为resolve_this.PromiseResult = data; // 返回结果setTimeout(() => { // 使用setTimeout 异步执行回调函数 reject同理_this.callbacks.forEach(item => { // 遍历回调数组,传入dataitem.onResolved(data)})});}function reject (data) { // 同上if (_this.PromiseState !== 'pending') {return;}_this.PromiseState = 'reject';_this.PromiseResult = data;setTimeout(() => {_this.callbacks.forEach(item => {item.onRejected(data)})});}try { // 使用try catch 来解决使用throw 改变promise状态executor(resolve, reject); // 执行executor 传入 resolve 和 reject 函数} catch (err) {reject(err);}}// promise原型上声明.then方法_Promise.prototype.then = function (onResolved, onRejected) {if (typeof onRejected !== 'function') { // then的第二个参数没传 给个默认值 抛出reasononRejected = reason => {throw reason; // 使用throw 完成catch穿透,链式调用中可以使用一个catch捕获到前面多个then的reject}}if (typeof onResolved !== 'function') { // then的第一参数没传,给onResolve设置一个默认值onResolved = value => value; // 接收一个value return 一个value 链式调用中就可以继续向后传值运行}return new _Promise((resolve, reject) => { // .then返回的是一个promise对象 见下面callback函数const _this = this; // 封装callback 在callback内可以访问到Promise实例// 封装then的调用函数,传入resolve和reject处理函数,try catch捕获throw// 在then的执行结果也会返回一个promise对象,如果return普通值便是resolve状态+return结果,function callback (fn) {try { // 避免回调也抛出错误let result = fn(_this.PromiseResult); // PromiseResult便是resolve时的参数if (result instanceof _Promise) { // 如果调用.then (即onResolved)返回的是一个promiseresult.then(v => { // 返回一个promise对象时resolve(v);}, r => {reject(r);});} else { // 如果return正常数据 调用resolve 传入 resultresolve(result);}} catch (err) { // 捕获错误 在then中throw也能rejectreject(err);}}// 执行.then,this指向的也是promise实例if (this.PromiseState === 'fulfilled') { //不同PromiseState执行不同回调setTimeout(() => { // 使用settimeout使then的回调函数异步执行 reject同理callback(onResolved);});}if (this.PromiseState === 'reject') {setTimeout(() => { // 使用settimeout使then的回调函数异步执行callback(onRejected);});}if (this.PromiseState === 'pending') { // 处理异步任务时 保存回调函数this.callbacks.push({ // callbacks回调数组,会在异步调用时在promise中调用onResolved: callback(onResolved),onRejected: callback(onRejected)})}})}// 添加catch方法 直接在调用then就行,onResolve传undefined_Promise.prototype.catch = function (onRejected) {return this.then(undefined, onRejected);}// resolve传入普通类型 必定返回成功,传入promise对象 返回状态等于传入的执行结果状态// 添加resolve方法,resolve方法是在Promise上调用的,不是在实例上调用的 所以不要写在原型上_Promise.resolve = function (value) {return new _Promise((resolve, reject) => { // resolve返回一个promise对象// 如果传入的是一个promise对象 那么resolve返回的就是 传入value的执行结果if (value instanceof _Promise) {value.then(v => {resolve(v);}, r => {reject(r);})} else { // 传入的不是promise 返回的是状态成功 resolveresolve(value);}})}// 添加reject方法 reject无论传入什么都是reject状态_Promise.reject = function (reason) {return new _Promise((resolve, reject) => { // 返回一个promise对象reject(reason); // 无论如何都是reject})}// 添加all方法, promise.all 接收一个promise的数组,// 全部resolve返回状态变为resolve返回结果为数组中所有promise的返回结果的数组,// 有一个不成功的便返回reject和当前失败的结果_Promise.all = function (promises) {let count = 0; // promises中执行成功的计数let arr = []; // 成功结果的数组return new _Promise((resolve, reject) => { // 返回的是一个promise对象for (let i in promises) { // 遍历传入的promise数组promises[i].then(v => { // 传入的都是promise对象 所以必然有then方法count++; // 状态为resolve 计数+1arr[i] = v; // 将结果存到数组,push也行 但保证返回结果和传入promise的顺序一致,使用下标赋值// 如果计数和传入数组长度相等,说明全部resolve 执行resolveif (count === promises.length) {resolve(arr);}}, r => { // 有一次reject 执行reject将结果返回reject(r);})}})}// 添加race方法,race也是接收一个promise的数组,返回状态和结果等于最先执行完的promise的状态和结果_Promise.race = function (promises) {return new _Promise((resolve, reject) => {for (let i in promises) {promises[i].then(v => {resolve(v);}, r => {reject(r);})}})}// 使用class写promise 把构造函数放在class的constructor中 then和catch直接写在class里// resolve、reject、all、race等方法写作静态属性 前面加static
