Promise
引用
我们先来看一段经典的代码:
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0) // 5、5、5、5、5
}
for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0) // 0、1、2、3、4
}
这其中蕴含了两个问题:
- var 的变量提升
setTimeout()
异步
什么是Promise
Promise 是异步编程的一种解决方案;
从语法上讲,Promise 是一个对象,从它可以获取异步操作的消息;
从本意上讲,它是承诺,承诺过一段时间给你一个结果;
Promise能解决什么问题
- 解决嵌套地狱
- promise支持多个并发的请求,获取并发请求中的数据
- promise可以解决异步的问题,但不能说promise本身是异步的
为什么说Promise本身不异步?
new Promise(() => {
console.log(1)
});
console.log(2)
// 1、2
// 原因是:
class _Promise() {
constructor(executor) {
executor(); // executor会马上被调用
}
}
Promise基础
Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样眼熟方法。
let p = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(() => {
console.log('执行完成');
resolve('我是成功!!');
}, 2000);
});
「基本原理」:
- Promise 是一个类,在执行这个类的时候会传入一个执行器,这个执行器会立即执行
- Promise 会有三种状态 • Pending 等待 • Fulfilled 完成 • Rejected 失败
- 状态只能由 Pending --> Fulfilled 或者 Pending --> Rejected,且一但发生改变便不可二次修改
- Promise 中使用 resolve 和 reject 两个函数来更改状态
- then 方法内部做但事情就是状态判断 • 如果状态是成功,调用成功回调函数 • 如果状态是失败,调用失败回调函数
「参数」:
- Promise构造函数的参数是executor(执行器,可以说是一个函数),接受两个参数resolve,reject
- 成功:将promise实例状态设置为fulfilled
- 失败:将promise实例状态设置为rejectd
「状态」:
- pending
- fulfilled
- rejected
.then( )
.then( )调用后返回的Promise对象的状态是pending || fulfilled || rejected ,主要取决于.then( )方法返回的值。
- 返回了一个参数值,返回的Promise为fulfilled
- 抛出了异常,返回的Promise为rejected
- 调用resolve( ),为fulfilled
- reject( ), rejected
- 返回pending状态的Promise实例,返回的Promise就是pending
- 若没resolve(data)/reject(data)/return data,返回的Promise是fulfilled,可以层层往下传递
Promise单一状态与状态
状态不可再改变。 Promise.then也是一个Promise。
手动实现一个Promise
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
status = PENDING;
value = null;
reason = null;
onFulfilledCallbacks = [];
onRejectedCallbacks = [];
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
resolve = value => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
while (this.onFulfilledCallbacks.length) {
this.onFulfilledCallbacks.shift()(value);
}
}
};
reject = reason => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
while ((this, this.onRejectedCallbacks.length)) {
this.onRejectedCallbacks.shift()(reason);
}
}
};
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : value => value;
onRejected =
typeof onRejected === "function"
? onRejected
: reason => {
throw reason;
};
const promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 微任务
queueMicrotask(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
} else if (this.status === REJECTED) {
queueMicrotask(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
} else if (this.status === PENDING) {
this.onFulfilledCallbacks.push(() => {
// ==== 新增 ====
queueMicrotask(() => {
try {
// 获取成功回调函数的执行结果
const x = onFulfilled(this.value);
// 传入 resolvePromise 集中处理
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push(() => {
// ==== 新增 ====
queueMicrotask(() => {
try {
// 调用失败回调,并且把原因返回
const x = onRejected(this.reason);
// 传入 resolvePromise 集中处理
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
});
return promise2;
}
static resolve(parameter) {
// 如果传入 MyPromise 就直接返回
if (parameter instanceof MyPromise) {
return parameter;
}
// 转成常规方式
return new MyPromise(resolve => {
resolve(parameter);
});
}
// reject 静态方法
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
}
function resolvePromise(promise, x, resolve, reject) {
// 如果相等了,说明return的是自己,抛出类型错误并返回
if (promise === x) {
return reject(
new TypeError("The promise and the return value are the same")
);
}
if (typeof x === "object" || typeof x === "function") {
// x 为 null 直接返回,走后面的逻辑会报错
if (x === null) {
return resolve(x);
}
let then;
try {
// 把 x.then 赋值给 then
then = x.then;
} catch (error) {
// 如果取 x.then 的值时抛出错误 error ,则以 error 为据因拒绝 promise
return reject(error);
}
// 如果 then 是函数
if (typeof then === "function") {
let called = false;
try {
then.call(
x, // this 指向 x
// 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
y => {
// 如果 resolvePromise 和 rejectPromise 均被调用,
// 或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
// 实现这条需要前面加一个变量 called
if (called) return;
called = true;
resolvePromise(promise, y, resolve, reject);
},
// 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
r => {
if (called) return;
called = true;
reject(r);
}
);
} catch (error) {
// 如果调用 then 方法抛出了异常 error:
// 如果 resolvePromise 或 rejectPromise 已经被调用,直接返回
if (called) return;
// 否则以 error 为据因拒绝 promise
reject(error);
}
} else {
// 如果 then 不是函数,以 x 为参数执行 promise
resolve(x);
}
} else {
// 如果 x 不为对象或者函数,以 x 为参数执行 promise
resolve(x);
}
}