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 => { // 遍历回调数组,传入data
item.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的第二个参数没传 给个默认值 抛出reason
onRejected = 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)返回的是一个promise
result.then(v => { // 返回一个promise对象时
resolve(v);
}, r => {
reject(r);
});
} else { // 如果return正常数据 调用resolve 传入 result
resolve(result);
}
} catch (err) { // 捕获错误 在then中throw也能reject
reject(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 返回的是状态成功 resolve
resolve(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 计数+1
arr[i] = v; // 将结果存到数组,push也行 但保证返回结果和传入promise的顺序一致,使用下标赋值
// 如果计数和传入数组长度相等,说明全部resolve 执行resolve
if (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