1.Promise解决回调地狱:
(1)回调函数延迟绑定:回调函数不是直接声明的,而是在通过后面的 then 方法传入的,即延迟传入。
(2)返回值穿透:异步方法并不会立即返回最终的值,而是会返回一个promise,后面可以依次完成链式调用。
(3)错误冒泡:前面产生的错误会一直向后传递,直到被 catch 接收到。
一.简易版实现
// 三大状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function myPromise(executor){
let self = this; //缓存当前Promise实例
self.status = PENDING; //当前状态
self.value = undefined; //成功传回的值
self.reason = undefined; //失败的原因
self.onFulfilled = undefined; //成功的回调
self.onRejected = undefined; //失败的回调
let resolve = (value)=>{
if (self.status === PENDING){
setTimeout(()=>{
self.status = FULFILLED;
self.value = value;
self.onFulfilled(self.value);//resolve时执行成功的回调。
},0)
}
}
let reject = (reason) =>{
if (self.status === PENDING){
setTimeout(()=>{
self.status = REJECTED;
self.reason = reason;
self.onRejected(self.reason);
},0)
}
}
// 如果exector执行报错,则直接执行reject
try{
executor(resolve,reject);
}catch(err){
reject(err);
}
}
myPromise.prototype.then = function(onFulfilled,onRejected){
if (this.status === PENDING){
this.onFulfilled = onFulfilled;
this.onRejected = onRejected;
}
if (this.status === FULFILLED){
// 如果状态时fulfilled,直接执行成功回调,并将成功的值传入
onFulfilled(this.value);
}
if (this.status === REJECTED){
// 如果状态时rejected,直接执行失败的回调,并将失败原因传入
onRejected(this.reason);
}
}
二.设置成回调数组
将回调函数处设置为数组:
self.onFulfilledCallbacks = [];
self.onRejectedCallbacks = [];
then函数中,当状态为PENDING时,将回调函数加入到数组中
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
在resolve和reject中对回调函数的执行进行部分修改:
// resolve 中
self.onFulfilledCallbacks.forEach((callback) => callback(self.value));
//reject 中
self.onRejectedCallbacks.forEach((callback) => callback(self.error));
全部代码如下:
// 三大状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function myPromise(executor){
let self = this; //缓存当前Promise实例
self.status = PENDING; //当前状态
self.value = undefined; //成功传回的值
self.reason = undefined; //失败的原因
self.onFulfilledCallbacks = []; //成功的回调
self.onRejectedCallbacks = []; //失败的回调
let resolve = (value)=>{
if (self.status === PENDING){
setTimeout(()=>{
self.status = FULFILLED;
self.value = value;
self.onFulfilledCallbacks.forEach((callback)=>{callback(this.value)});//resolve时依次执行成功的回调。
},0)
}
}
let reject = (reason) =>{
if (self.status === PENDING){
setTimeout(()=>{
self.status = REJECTED;
self.reason = reason;
self.onRejectedCallbacks((callback)=>{callback(self.reason)});
},0)
}
}
// 如果exector执行报错,则直接执行reject
try{
executor(resolve,reject);
}catch(err){
reject(err);
}
}
myPromise.prototype.then = function(onFulfilled,onRejected){
if (this.status === PENDING){
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
if (this.status === FULFILLED){
// 如果状态时fulfilled,直接执行成功回调,并将成功的值传入
onFulfilled(this.value);
}
if (this.status === REJECTED){
// 如果状态时rejected,直接执行失败的回调,并将失败原因传入
onRejected(this.reason);
}
return this;
}
三.解决链式调用
解决链式调用:
1、若为链式调用,我们默认在第一个then里返回的是一个promise。
•若返回的是promise则传递到下一个then中。
•如果返回一个普通的值,则将普通的值传递给下一个then中。
2、当我们在第一个then中 return 了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()或onRejected()的值
秘籍则规定onFulfilled()或onRejected()的值,即第一个then返回的值,叫做x,判断x的函数叫做resolvePromise
// 三大状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function myPromise(executor) {
let self = this; //缓存当前myPromise实例
self.status = PENDING; //当前状态
self.value = undefined; //成功传回的值
self.reason = undefined; //失败的原因
self.onFulfilledCallbacks = []; //成功的回调
self.onRejectedCallbacks = []; //失败的回调
let resolve = (value) => {
if (self.status === PENDING) {
setTimeout(() => {
self.status = FULFILLED;
self.value = value;
self.onFulfilledCallbacks.forEach((callback) => { callback(this.value) });//resolve时依次执行成功的回调。
}, 0)
}
}
let reject = (reason) => {
if (self.status === PENDING) {
setTimeout(() => {
self.status = REJECTED;
self.reason = reason;
self.onRejectedCallbacks.forEach((callback) => { callback(self.reason) });
}, 0)
}
}
// 如果exector执行报错,则直接执行reject
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
// onFulfilled, onRejected都是可选参数,如果他们不是函数,必须被忽略
// • onFulfilled返回一个普通的值,成功时直接等于 value => value
// • onRejected返回一个普通的值,失败时如果直接等于 value => value,则会跑到下一个then中的onFulfilled中,所以直接扔出一个错误 reason => throw err
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
let bridgemyPromise;
let self = this;
if (self.status === PENDING) {
return bridgemyPromise = new myPromise((resolve, reject) => {
self.onFulfilledCallbacks.push((value) => {
setTimeout(() => {
try {
let x = onFulfilled(value);
resolvemyPromise(bridgemyPromise, x, resolve, reject);
} catch (reason) {
reject(reason);
}
}, 0)
});
self.onRejectedCallbacks.push((reason) => {
setTimeout(() => {
try {
let x = onRejected(reason);
resolvemyPromise(bridgemyPromise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
})
})
}
if (this.status === FULFILLED) {
// 如果状态时fulfilled,直接执行成功回调,并将成功的值传入
return bridgemyPromise = new myPromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onFulfilled(self.value);
resolvemyPromise(bridgemyPromise, x, resolve, reject);
}
catch (reason) {
reject(reason);
}
}, 0)
})
}
if (this.status === REJECTED) {
// 如果状态时rejected,直接执行失败的回调,并将失败原因传入
return bridgemyPromise = new myPromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(self.reason);
resolvemyPromise(bridgemyPromise, x, resolve, reject);
}
catch (reason) {
reject(reason);
}
})
})
}
return bridgemyPromise;
}
其中一个重要的函数实现为:
// 兼容实现多种myPromise
function resolvemyPromise(bridgemyPromise, x, resolve, reject) {
// 防止循环引用的问题
if (bridgemyPromise === x) {
return reject(new TypeError('Error'));
}
// called变量,用于判断是否已经调用过函数
let called;
// 判断x是否为对象或者函数,如果都不是,则将x传入resolve中
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
// 如果x是对象或者函数的话,把x.then赋值给then,然后判断then的类型,如果不是函数类型的话,将x传入resolve中
let then = x.then;
// 如果then是函数,就默认是myPromise
if (typeof then === 'function') {
// 让then执行,第一个参数是this,后面是成功的回调和失败的回调
then.call(x, y => {
if (called) return;
called = true;
resolvemyPromise(bridgemyPromise, x, resolve, reject);
}, reason => {
if (called) return;
called = true;
reject(reason);
})
}
else {
resolve(x);
}
}
catch (reason) {
if (called) return;
called = true;
reject(reason);
}
}
else {
resolve(x);
}
}
四.解决错误捕获及冒泡机制
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
}
五.catch和resolve、reject、race、all方法
文章借鉴: (1)developer.mozilla.org/zh-CN/docs/… (2)www.cnblogs.com/sugar-tomat… (3)juejin.cn/post/684490…