在上一章中讲了事件循环和任务队列,里面有一个关键词是异步.我们讲到了异步就不得不提Promise(这部分内容比较多,可能会分为2章来讲).
Promise是什么
Promise是es6发布的新特性之一,对于现在来说也已经不新了,他已经发布了7年了,但是我们还是经常的使用他,时间证明了他的强大. Promise翻译过来就是承诺,在<<你不知道的JavaScript>>中是这样解释的,你去买汉堡,在柜台上,下订单付款,得到一个凭证,启动了一场交易.这个凭证代表了你未来的汉堡,你只需要耐心等待就行,期间你可以干其他事情,比如刷刷抖音. 你只需要时间到了,凭你手上的凭证去换取你的汉堡就行,但是也有可能出现另外一种情况,到了你的号的时候,服务员告诉你,你好意思,我们的汉堡买完了.这也是代表着promise的特性可能成功,也有可能失败.在代码中,事情并非这么简单。这是因为,用类比的方式来说就是,订单号可能永远不会被叫到。在这种情况下,我们就永远处于一种未决议状态。后面会讨论如何处理这种情况。
Promise能干什么
我们先来控制台输出一下Promise有什么功能.
我们可以看到Promise是一个构造函数,上面有我们熟悉的race,reject,resolve函数和原型链上的catch,finally,then函数
很多的开发者说Promise是为了解决毁掉地狱(有时间的话可以详细解释)而出现的.但是只是为了解决回调地狱对于已经2022年的现在来说似乎有点单薄了.现在我们在开发中涉及到异步的任务,我们都会想到Promise或者async await.这在一定程度上是升华了Promise的功能.
在异步操作我们往往会去获取到这个异步操作的结果,如果不用Promise我们往往会使用回调的形式,Promise可以使用.then.catch的方式去获取,虽然在链式编程中也是回调,但是规范了很多.
而且对于错误的情况也做了处理.
深入Promise
开始准备讲Promise的状态,resolve,reject,.then .catch...都已经快写完了,后来想了想不太直观.想换一种方式,有什么方式比手写一个自己的Promise更加直观了,所以
Promise的三种状态
const PENDING = 'pending';
const RESOVLED = 'resolved';
const REJECTED = 'rejected';
定义一个Promise类
初始化数据
class MyPromise {
constructor(executor) {
let that = this;
this.status = PENDING; //状态未变之前都是pending
this.data = undefined; //未定义的数据
this.callbacks = []; //每个元素的结构:onResolved(){},onRejected(){}
}
}
定义Promise的resolve和reject 和回调错误捕获
function resolve(value) {
if (that.status !== PENDING) return;
//调用resolve后,需要将状态改变成为resolved
that.status = RESOVLED;
//保存data数据
that.data = value;
//如果有未执行的callback,则立即异步执行onResolved,是包含两个回调的对象
if (that.callbacks.length > 0) {
setTimeout(() => {
that.callbacks.forEach((element) => {
element.onResolved(value);
});
});
}
}
function reject(reason) {
if (that.status !== PENDING) return;
//调用reject后,需要将状态改变成为rejected
that.status = REJECTED;
//保存data数据
that.data = reason;
//如果有未执行的callback,则立即异步执行onRejected,是包含两个回调的对象
if (that.callbacks.length > 0) {
setTimeout(() => {
that.callbacks.forEach((element) => {
element.onResolved(reason);
});
});
}
}
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
.then接收成功失败的回调返回新的MyPromise
then(onResolved, onRejected) {
const that = this;
// 指定回调函数的默认值(必须是函数)
onResolved =
typeof onResolved === 'function' ? onResolved : (value) => value; //继续向下传递
onRejected =
typeof onRejected === 'function'
? onRejected
: (reason) => {
throw reason;
}; //抛出异常
return new MyPromise((resolve, reject) => {
if (this.status === PENDING) {
//假设当前状态还是pending,将回调保存下来
this.callbacks.push({
onResolved(value) {
onResolved(that.data);
try {
const result = onResolved(that.data);
if (result instanceof MyPromise) {
result.then(
resolve,
reject
);
}
} catch (error) {
resolve(error);
}
},
onRejected(reason) {
onRejected(that.data);
try {
const result = onRejected(that.data);
if (result instanceof MyPromise) {
result.then(
resolve,
reject
);
}
} catch (error) {
reject(error);
}
}
});
} else if (this.status === RESOVLED) {
setTimeout(() => {
// 如果回调是MyPromise,return的MyPromise结果就是这个MyPromise结果
try {
const result = onResolved(that.data);
if (result instanceof MyPromise) {
result.then(
resolve,
reject
);
} else {
//返回的不是promise,返回promise为成功,value就是返回值
resolve(result);
}
} catch (error) {
reject(error);
}
});
} else {
//如果前面的promise返回的是失败的回调
setTimeout(() => {
// 如果回调是promise,return的promise结果就是这个promise结果
try {
const result = onRejected(that.data);
if (result instanceof MyPromise) {
result.then(
resolve,
reject
);
}
} catch (error) {
try {
const result = onResolved(that.data);
if (result instanceof MyPromise) {
result.then(
resolve,
reject
);
}
} catch (error) {
reject(error);
}
}
});
}
});
}
.catch接受失败回调
catch(onRejected) {
return this.then(undefined, onRejected);
}
promise函数对象的resolve方法
static resolve(value) {
return new MyPromise((resolve, reject) => {
if (value instanceof MyPromise) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
promise函数对象的reject方法
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}