调用Promise
//#region 测试then方法let p = new Promise((resolve, reject) => {// setTimeout(() => {// // resolve('ok')// reject('no')// }, 1000);// resolve('ok')reject('no~')// throw 'Error'});p.then(v => {console.log(v)}, r => {console.log(r)})//#endregion//#region 测试Promise对象返回结果// let p = new Promise((resolve, reject) => {// // setTimeout(() => {// // // resolve('ok')// // reject('no')// // }, 1000);// // resolve('ok')// reject('no~')// // throw 'Error'// });// console.log(p);//#endregion//#region 测试then方法返回对象// const res = p.then(value => {// // console.log(value);// // return '213'// // throw 'ERROR'// return new Promise((resolve, reject) => {// resolve('888')// })// }, reason => {// // return '213'// // return new Promise((resolve, reject) => {// // reject('888')// // })// // console.log(reason);// })// console.log(res);//#endregion//#region 测试catch// p.then(value => {// console.log(111);// })// .then(value => {// console.log(222);// })// .then(value => {// console.log(333);// })// .catch(reason => {// console.log(reason);// })//#endregion//#region 测试resolve & reject// let p1 = Promise.resolve('ok');// const p2 = Promise.resolve(new Promise((resolve, reject) => {// // resolve('Success');// reject("error");// }));// const p3 = Promise.resolve(Promise.resolve('Oh Yeah'));// console.log(p1);// console.log(p2);// console.log(p3);// let p4 = Promise.reject('no');// let p5 = Promise.reject(new Promise((resoleve, reject) => {// reject('no for Promise')// }));// let p6 = Promise.reject(Promise.resolve('ok'))// let p7 = Promise.reject(Promise.reject('no~'))// console.log(p4);// console.log(p5);// console.log(p6);// console.log(p7);//#endregion//#region 测试all方法// let p1 = new Promise((resolve, reject) => {// resolve('ok1')// });// let p2 = new Promise((resolve, reject) => {// reject('ok2')// });// let p3 = new Promise((resolve, reject) => {// resolve('ok3')// });// let res = Promise.all([p1, p2, p3]);// console.log(res);//#endregion//#region 测试race方法// let p1 = new Promise((resolve, reject) => {// setTimeout(function () {// resolve('ok1')// })// })// let p2 = Promise.reject('ok2')// let p3 = Promise.resolve('ok3')// let res = Promise.race([p1, p2, p3])// console.log(res);//#endregion//#region 测试then函数异步回调// let p1 = new Promise((resolve, reject) => {// resolve('OK');// console.log(111);// });// p1.then(value => {// console.log(222);// });// console.log(333);// //111 333 222//#endregion
定义Promise
定义过程中的注意点
传进来的是Promise 为什么要.then呢? 因为这样才能拿到该Promise对象返回的结果,再交给resolve或reject去执行,否则抛过去一个Promise对象,PromiseResult 结果就是给Promise对象的返回值
定义思路
- 初始结构搭建
- resolve与reject结构搭建
- resolve与reject函数实现
throw抛出错误改变状态
try {executor(resolve, reject)} catch (error) {reject(error)}
状态只能修改一次
if (this.PromiseState !== 'pending') return;- then方法执行回调
异步任务then方法执行回调
if (this.PromiseState === 'pending') {this.callbacks.push({onResolve() {callback(onResolved)},onRejected() {callback(onRejected)}})}
指定多个回调
this.callbacks.forEach(item => {item.onResolve(data)})
同步修改状态then方法返回结果
callback(onResolve)- 异步修改状态then方法返回结果
onResolve() { callback(onResolved) } - catch方法与异常穿透
this.then(undefined, onRejected) - Promise.resolve
- Promise.reject
reject(reason) - Promise.all方法实现
if (count === promises.length) { resolve(arr) } - Promise.race方法实现
then回调函数异步执行的实现
onResolve() { callback(onResolved) }普通构造函数
```javascript function Promise(executor) {
// 添加属性 this.PromiseState = ‘pending’; //返回的状态 this.PromiseResult = null; //返回的结果 this.callbacks = [];
const self = this;
//resolve 函数 function resolve(data) { //连续调用resolve|reject时状态只能修改一次 if (self.PromiseState !== ‘pending’) return; //1. 修改对象的状态 (promiseState)为成功 self.PromiseState = ‘fulfilled’; //2. 设置对象结果值 (promiseResult) self.PromiseResult = data;
//变为异步微任务 queueMicrotask(() => { //异步调用时,执行then保存的onRejected方法 self.callbacks.forEach(item => {
item.onResolved(data)
}); }) }
//reject 函数 function reject(data) { //连续调用resolve|reject时状态只能修改一次 if (self.PromiseState !== ‘pending’) return; //1. 修改对象的状态 (promiseState)为成功 self.PromiseState = ‘rejected’; //2. 设置对象结果值 (promiseResult) self.PromiseResult = data;
//变为异步微任务 queueMicrotask(() => { //异步调用时,执行then保存的onRejected方法 self.callbacks.forEach(item => {
item.onRejected(data);}); }) }
try { //同步调用『执行器函数』 executor(resolve, reject); } catch (err) { reject(err) } }
//添加 then 方法 Promise.prototype.then = function (onResolved, onRejected) {
//判断回调函数参数 //如果用户没有定义onRejected,那么在reject中就会报错,所有给添加一个默认函数 //该函数抛出异常,以此达到一出错可以一直往后抛(下一个接收上一个的异常) 直到抛到catch实现穿透 if (typeof onRejected !== ‘function’) { //因为这里本来就是出错的回调 所以可以直接抛错 onRejected = reason => { throw reason } } //当用户没指定成功回调时resolve会找不到而报错 if (typeof onResolved !== ‘function’) { onResolved = value => value }
/ then方法返回结果 一定是一个Promise对象,当then返回不同值时会响应返回不同的结果 [[PromiseState]]: “fulfilled” || “rejected”,[[PromiseResult]]: “执行返回的结果!” 1.Promise对象 状态为该对象返回的状态,返回值为对象的值 2.非Promise对象 状态为成功, 返回值为对象的成功的值 3.抛出错误 状态为失败, 返回值为对象的值 / / return中使用了 => this向外找到找 依然指向构造函数。 如果是普通函数,因为没有被谁调用所以指向window。 * 这里的return的就是一个新的构造函数( Promise) 与用户const p = new Promise该构造函数无关。 其中调用的resolve和reject也是, 其作用只是返回对应的状态和结果而已, 不会修改到p的结果 1.这里的Promise是自己定义的所以return的就是该构造函数, 也就是传入的这个参数(函数new Promise) new之后Promise函数会执行executor, 自然里边的代码也会被执行, 并返回初始结果(PromiseState: ‘pending’和PromiseResult:null)
2. 因为要返回不同的状态和结果, 所以可以在下方调用成功或失败回调时根据返回值修改状态和结果( 有executor所以下方函数会被执行一遍),
3.
*/ const self = this; return new Promise((resolve, reject) => {
//定义一个公用函数
function callback(type) {
//当then返回的是抛出错误时,返回失败的状态和结果
try {
const result = type(self.PromiseResult);
// 根据then的返回值修改对应的状态和结果
if (result instanceof Promise) {
//如果result是Promise(该对象是新new的),那它身上就有then方法,then方法接收resolve或reject的结果,
//所以能根据result的执行结果拿到value或reason,并调用对应的方法修改状态和结果
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//如果不是Promise 则返回成功状态和结果
//原生Promise在失败回调中 then返回的也是返回成功状态
//调用resolve修改状态和结果
resolve(result)
}
} catch (error) {
reject(error);
}
}
//该回调p.then , this指向实例对象p
//调用成功回调
if (this.PromiseState === 'fulfilled') {
//变为异步微任务
queueMicrotask(() => {
callback(onResolved);
});
}
//调用失败回调
if (this.PromiseState === 'rejected') {
//变为异步微任务
queueMicrotask(() => {
callback(onRejected);
});
}
//如果是异步 则还来不及调用resolve或reject,所以要把调用then的方法交给resolve或reject
//待用户异步执行resolve或reject时让其调用
if (this.PromiseState === 'pending') {
//保存这两个方法到构造函数上,用于给resolve或reject调用
//不能保存到原型上,因为原型链上的属性是共享的,多个对象实例则会修改到
//因为then是可以连续调用多个的 所以用数组循环指向
this.callbacks.push({
//异步原因本来直接将onResolved或onRejected交给resolve执行,但因为需要then返回状态和结果,
//所以对then的回调函数进行修改,在修改的函数里也有执行了一遍onResolved或onRejected,所以没有问题
//成功回调
onResolved: function () {
callback(onResolved)
},
//失败回调
onRejected: function () {
callback(onRejected)
}
})
}
}) }
//添加 catch 方法 // 原生Promise的catch方法: 如果指定了某一个失败回调则执行该回调, // 如果未指定了失败回调则一直往下穿透直到catch,这一功能在then方法中(throw reason)实现 Promise.prototype.catch = function (onRejected) { //catch方法是捕捉失败的方法,所以实例对象一定是返回reject, //所以调用then方法接收onRejected回调函数,不需要成功所以onReolve=undefined this.then(‘undefined’, onRejected) }
//添加 resolve 方法 Promise.resolve = function (value) { return new Promise((resolve, reject) => { if (value instanceof Promise) { value.then(v => { resolve(v) }, r => { reject(r) }) } else { resolve(value) } }) }
//添加 reject 方法 //原生reject //状态:一定是失败,不管传入是否为Promise对象 //结果:返回传入的结果,如果是Promise也返回Promise Promise.reject = function (reason) { return new Promise((resolve, reject) => { reject(reason) }) }
//添加 all 方法 Promise.all = function (promises) { //返回的结果是一个Promise对象 状态:根据情况 结果:[] || 报错 return new Promise((resolve, reject) => { //用于计算每个Promise是否执行成功 let count = 0; let arr = []; promises.forEach((item, index) => { //拿到的是一个个Promise对象 item.then(v => { //每个promise对象 都成功 count++; //将当前promise对象成功的结果 根据顺序存入到数组中 arr[index] = v; //都成功后才能执行resolve修改状态和结果,否则有错误的时候无法再调用 if (count === promises.length) { //将结果数组作为参数传出 resolve(arr) } }, r => { //有一个失败则可以直接修改状态为失败和结果:失败的结果 reject(r) }) }) }) }
//添加 race 方法 //谁先执行完,无论成功失败 Promise.race = function (promises) { return new Promise((resolve, reject) => { promises.forEach(item => { item.then(v => { //修改返回对象的状态为 『成功』 resolve(v) }, r => { //修改返回对象的状态为 『失败』 reject(r) }) }) }) }
<a name="nmpC8"></a>
### class定义
普通函数版本 可以看到this指向问题
```javascript
class Promise {
constructor(executor) {
// 添加属性
this.PromiseState = 'pending'; //返回的状态
this.PromiseResult = null; //返回的结果
this.callbacks = [];
const self = this;
//resolve 函数
function resolve(data) {
if (self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)为成功
self.PromiseState = 'fulfilled';
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//变为异步微任务
queueMicrotask(() => {
//异步调用时,执行then保存的onRejected方法
self.callbacks.forEach(item => {
item.onResolved(data)
});
})
}
//reject 函数
function reject(data) {
if (self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)为成功
self.PromiseState = 'rejected';
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//变为异步微任务
queueMicrotask(() => {
//异步调用时,执行then保存的onRejected方法
self.callbacks.forEach(item => {
item.onRejected(data);
});
})
}
try {
//同步调用『执行器函数』
executor(resolve, reject);
} catch (err) {
reject(err)
}
}
//添加 then 方法
then(onResolved, onRejected) {
//判断回调函数参数
//如果用户没有定义onRejected,那么在reject中就会报错,所有给添加一个默认函数
//该函数抛出异常,以此达到一出错可以一直往后抛(下一个接收上一个的异常) 直到抛到catch实现穿透
if (typeof onRejected !== 'function') {
//因为这里本来就是出错的回调 所以可以直接抛错
onRejected = reason => {
throw reason
}
}
//当用户没指定成功回调时resolve会找不到而报错
if (typeof onResolved !== 'function') {
onResolved = value => value
}
/*
then方法返回结果 一定是一个Promise对象,当then返回不同值时会响应返回不同的结果
[[PromiseState]]: "fulfilled" || "rejected",[[PromiseResult]]: "执行返回的结果!"
1.Promise对象 状态为该对象返回的状态,返回值为对象的值
2.非Promise对象 状态为成功, 返回值为对象的成功的值
3.抛出错误 状态为失败, 返回值为对象的值
*/
/*
** return中使用了 => this向外找到找 依然指向构造函数。 如果是普通函数,因为没有被谁调用所以指向window。**
** 这里的return的就是一个新的构造函数( Promise) 与用户const p = new Promise该构造函数无关。
其中调用的resolve和reject也是, 其作用只是返回对应的状态和结果而已, 不会修改到p的结果 **
1.这里的Promise是自己定义的所以return的就是该构造函数, 也就是传入的这个参数(函数new Promise)
new之后Promise函数会执行executor, 自然里边的代码也会被执行, 并返回初始结果(PromiseState: 'pending'和PromiseResult:null)
2. 因为要返回不同的状态和结果, 所以可以在下方调用成功或失败回调时根据返回值修改状态和结果( 有executor所以下方函数会被执行一遍),
3.
*/
const self = this;
return new Promise((resolve, reject) => {
//定义一个公用函数
function callback(type) {
//当then返回的是抛出错误时,返回失败的状态和结果
try {
const result = type(self.PromiseResult);
// 根据then的返回值修改对应的状态和结果
if (result instanceof Promise) {
//如果result是Promise(该对象是新new的),那它身上就有then方法,then方法接收resolve或reject的结果,
//所以能根据result的执行结果拿到value或reason,并调用对应的方法修改状态和结果
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//如果不是Promise 则返回成功状态和结果
//原生Promise在失败回调中 then返回的也是返回成功状态
//调用resolve修改状态和结果
resolve(result)
}
} catch (error) {
reject(error);
}
}
//该回调p.then , this指向实例对象p
//调用成功回调
if (this.PromiseState === 'fulfilled') {
//变为异步微任务
queueMicrotask(() => {
callback(onResolved);
});
}
//调用失败回调
if (this.PromiseState === 'rejected') {
//变为异步微任务
queueMicrotask(() => {
callback(onRejected);
});
}
//如果是异步 则还来不及调用resolve或reject,所以要把调用then的方法交给resolve或reject
//待用户异步执行resolve或reject时让其调用
if (this.PromiseState === 'pending') {
//保存这两个方法到构造函数上,用于给resolve或reject调用
//不能保存到原型上,因为原型链上的属性是共享的,多个对象实例则会修改到
//因为then是可以连续调用多个的 所以用数组循环指向
this.callbacks.push({
//异步原因本来直接将onResolved或onRejected交给resolve执行,但因为需要then返回状态和结果,
//所以对then的回调函数进行修改,在修改的函数里也有执行了一遍onResolved或onRejected,所以没有问题
//成功回调
onResolved: function () {
callback(onResolved)
},
//失败回调
onRejected: function () {
callback(onRejected)
}
})
}
})
}
//添加 catch 方法
// 原生Promise的catch方法: 如果指定了某一个失败回调则执行该回调,
// 如果未指定了失败回调则一直往下穿透直到catch,这一功能在then方法中(throw reason)实现
catch (onRejected) {
//catch方法是捕捉失败的方法,所以实例对象一定是返回reject,
//所以调用then方法接收onRejected回调函数,不需要成功所以onReolve=undefined
this.then('undefined', onRejected)
}
/*********以下添加静态方法,不属于原型*********/
//添加 resolve 方法
static resolve(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(value)
}
})
}
//添加 reject 方法
//原生reject
//状态:一定是失败,不管传入是否为Promise对象
//结果:返回传入的结果,如果是Promise也返回Promise
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
//添加 all 方法
static all(promises) {
//返回的结果是一个Promise对象 状态:根据情况 结果:[] || 报错
return new Promise((resolve, reject) => {
//用于计算每个Promise是否执行成功
let count = 0;
let arr = [];
promises.forEach((item, index) => {
//拿到的是一个个Promise对象
item.then(v => {
//每个promise对象 都成功
count++;
//将当前promise对象成功的结果 根据顺序存入到数组中
arr[index] = v;
//都成功后才能执行resolve修改状态和结果,否则有错误的时候无法再调用
if (count === promises.length) {
//将结果数组作为参数传出
resolve(arr)
}
}, r => {
//有一个失败则可以直接修改状态为失败和结果:失败的结果
reject(r)
})
})
})
}
//添加 race 方法
//谁先执行完,无论成功失败
static race(promises) {
return new Promise((resolve, reject) => {
promises.forEach(item => {
item.then(v => {
//修改返回对象的状态为 『成功』
resolve(v)
}, r => {
//修改返回对象的状态为 『失败』
reject(r)
})
})
})
}
}
箭头函数版本 解决this指向问题
// es6 class + 箭头函数解决this指向问题
class Promise {
constructor(executor) {
this.PromiseState = 'pending';
this.PromiseResult = null;
this.callbacks = [];
//箭头函数让this执行外层
const resolve = (data) => {
if (this.PromiseState !== 'pending') return;
this.PromiseState = 'fulfilled';
this.PromiseResult = data;
queueMicrotask(() => {
this.callbacks.forEach(item => {
item.onResolved(data)
})
})
}
const reject = (data) => {
if (this.PromiseState !== 'pending') return;
this.PromiseState = 'rejected';
this.PromiseResult = data;
queueMicrotask(() => {
this.callbacks.forEach(item => {
item.onRejected(data)
})
})
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onResolved, onRejected) {
if (typeof onRejected !== 'function') {
onRejected = (reason) => {
throw reason
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve, reject) => {
const callback = (type) => {
try {
const result = type(this.PromiseResult);
if (result instanceof Promise) {
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
if (this.PromiseState === 'fulfilled') {
queueMicrotask(() => {
callback(onResolved)
})
}
if (this.PromiseState === 'rejected') {
queueMicrotask(() => {
callback(onRejected)
})
}
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved() {
callback(onResolved)
},
onRejected() {
callback(onRejected)
}
})
}
})
}
catch (onRejected) {
this.then(undefined, onRejected)
}
static resolve(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(value)
}
})
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
static all(promises) {
return new Promise((resolve, reject) => {
let count = 0;
let arr = [];
promises.forEach((item, index) => {
item.then(v => {
count++;
arr[index] = v;
if (count === promises.length) {
resolve(arr)
}
}, r => {
reject(r)
});
})
})
}
static race(promises) {
return new Promise((resolve, reject) => {
promises.forEach(item => {
item.then(v => {
resolve(v)
}, r => {
reject(r)
});
})
})
}
}
