概念
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise
对象。
所谓Promise
,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise 拉出来单练
那我们先把Promise拉出来练练,看看是什么玩意,在控制台中打印看下
- 首先我们看出在
new Promise
时,需要传入一个回调函数 - 它是一个类,并且会返回一个Promise对象
- 那还可以看出它有
constructor
构造函数,还有catch
、finally
、then
三个方法
那我们根据上述分析出的信息,简单实现一下
class CustomPromise {
constructor(callBack) {}
catch() {}
then() {}
finally() {}
}
const customPromise = new CustomPromise()
console.log(customPromis)
看下我们自己简单实现的输出结果
const promise = new Promise((resolve, reject) => {
console.log("hellow Promise");
});
console.log(promise);
那我们来看看打印结果,能分析出什么结果
- hellow promise 在控制台被输出了,那是不是说我们传入的回调函数被立即执行了,那说明传入的是一个执行器
那再改进一下我们的CustomPromise
class CustomPromise {
constructor(executor) {
executor()}
catch() { }
then() { }
finally() { }
}
const customPromise = new CustomPromise((resolve, reject) => {
console.log('hellow Promise')
})
console.log(customPromise)
Promise基本原理与基本特征
那我们来看看我们所熟知的Promise
的基本原理
- 首先我们在调用Promise时,会返回一个Promise对象。
- 构建Promise对象时,需要传入一个executor函数,Promise的主要业务流程都在executor函数中执行。
- 如果运行在excutor函数中的业务执行成功了,会调用resolve函数;如果执行失败了,则调用reject函数。
- Promise的状态不可逆,同时调用resolve函数和reject函数,默认会采取第一次调用的结果。
结合Promise/A+规范,我们还可以分析出哪些基本特征
Promise/A+的规范比较多,在这列出一下核心的规范
- promise有三个状态:pending,fulfilled,rejected,默认状态是pending。
- promise有一个value保存成功状态的值,有一个reason保存失败状态的值,可以是undefined/thenable/promise。
- promise只能从pending到rejected, 或者从pending到fulfilled,状态一旦确认,就不会再改变。
- promise 必须有一个then方法,then接收两个参数,分别是promise成功的回调onFulfilled, 和promise失败的回调onRejected。
- 如果then中抛出了异常,那么就会把这个异常作为参数,传递给下一个then的失败的回调onRejected。
那CustomPromise
,还实现不了基本原理的3,4两条,那我们来根据基本原理与Promise/A+分析下,还缺少什么
- promise有三个状态:pending,fulfilled,rejected。
- executor执行器调用reject与resolve两个方法
- 还需要有保存成功或失败两个值的变量
- then接收两个参数,分别是成功的回调onFulfilled,失败的回调onRejected
那再来改进下CustomPromise
// 定义三个常量表示状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class CustomPromise {
constructor(executor) {
executor(this.resolve, this.reject);}
// resolve和reject为什么要用箭头函数?
// 如果直接调用的话,普通函数this指向的是window或者undefined
// 用箭头函数就可以让this指向当前实例对象
resolve = (value) => {
this.value = value;};
reject = (value) => {
this.reason = value;};
// 成功之后的值
value = undefined;
// 失败之后的值
reason = undefined;
then(onFulfilled,onRejected) {}
catch() {}
finally() {}
}
那我们根据Promise基本原理看看它原生Promise的效果
new Promise(function (resolve, reject) {
resolve("成功");
reject("失败");
}).then((value) => {
console.log(value); // 结果为‘成功’},(err) => {
console.log(err);}
);
new Promise(function (resolve, reject) {
reject("失败");
resolve("成功");
}).then((value) => {
console.log(value);},(err) => {
console.log(err); // 结果为‘失败’}
);
可以看出与基本原理一样的效果,那我们分析下如何实现这种效果
- 需要控制promise状态
- 在then方法里要调用成功或失败的回调函数
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class CustomPromise {
constructor(executor) {
executor(this.resolve, this.reject);}
// resolve和reject为什么要用箭头函数?
// 如果直接调用的话,普通函数this指向的是window或者undefined
// 用箭头函数就可以让this指向当前实例对象
resolve = (value) => {
// promise只能从pending到rejected, 或者从pending到fulfilled
if (this.status == PENDING) {
this.status = FULFILLED;
this.value = value;
}};
reject = (err) => {
// promise只能从pending到rejected, 或者从pending到fulfilled
if (this.status == PENDING) {
this.status = REJECTED;
this.reason = err;
}};
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的值
reason = undefined;
then(onFulfilled, onRejected) {
// 需要判断状态,根据状态选择处理回调函数
if (this.status == FULFILLED) {
onFulfilled(this.value);
} else if (this.status == REJECTED) {
onRejected(this.reason);
}}
catch() {}
finally() {}
}
来测试下CustomPromise
new CustomPromise(function (resolve, reject) {
resolve("成功");
reject("失败");
}).then((value) => {
console.log(value);// 结果为‘成功’},(err) => {
console.log(err);}
);
new CustomPromise(function (resolve, reject) {
reject("失败");
resolve("成功");
}).then((value) => {
console.log(value);},(err) => {
console.log(err);// 结果为‘失败’}
);
Promise.then链式调用
我们都知到Primose.then是可以链式调用的,那我们先看看原生效果
const promise = new Promise((resolve, reject) => {
resolve("start");
});
promise.then((res) => {
console.log(res);
return new Pr