彻底搞懂Promise原理
一、先讲一下promise的规范:
Promise A+规范是 Promise 所遵循的标准,由Promises/A+组织提出并维护,主要规定了 Promise 的行为和接口,以确保 Promise 的可靠性和可互操作性。
以下是 Promise A+ 规范的主要内容:
1. Promise 状态
Promise 状态分为三种:pending(等待态)、fulfilled(成功态)和 rejected(失败态)。状态的变更只能是从 pending 转换到 fulfilled 或 rejected,并且变更后不能再次改变。
2. then 方法
Promise 实例必须提供一个 then 方法,用于处理 Promise 的状态变更。then 方法可以接收两个参数:onFulfilled 和 onRejected 分别表示在 Promise 状态变为 fulfilled 和 rejected 时需要执行的回调函数。then 方法返回一个新的 Promise 实例。
3. 回调执行
当 Promise 状态变为 fulfilled 后,必须按照 then 方法注册回调的顺序依次执行所有回调函数;当状态变为 rejected 后,也必须按照注册顺序依次执行所有 rejected 回调。如果某个回调不存在,则忽略之。
4. 异步执行
Promise 的 then 方法必须异步执行(即在本轮事件循环结束之后),且应该优先采用 microtask 队列而非 macrotask 队列执行。
5. then 方法链式调用
Promise 的 then 方法应该支持链式调用,即 then 方法必须返回一个新的 Promise 实例,并在上面注册回调函数。
6. 值穿透
Promise.then 调用传递的值可以是简单的常量值或一个新的 Promise 对象,甚至可以是出现 thenable 表示合法的对象,这样的话必须在线程安全的情况下处理这个对象的值。
以上就是 Promise A+ 规范的内容,目的是统一各种 Promise 实现方式,使其具有互操作性。
总结来说就是:
- new Promise时需要传递一个executor执行器,执行器会立刻执行;
- 执行器中传递了两个参数 resolve成功的函数 他调用时可以传一个值 值可以是任何值 reject失败的函数 他调用时可以传一个值 值可以是任何值;
- 只能从pending态转到成功或者失败;
- promise实例,每个实例都有一个then方法,这个方法传递两个参数,一个是成功另一个是失败;
- 如果调用then时 发现已经成功了 会让成功函数执行并且把成功的内容当作参数传递到函数中;
- promise 中可以同一个实例then多次,如果状态是pending 需要将函数存放起来 等待状态确定后 在依次将对应的函数执行 (发布订阅);
- 如果类执行时出现了异常 那就变成失败态。
完整实现代码
function Promise(executor) {
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
self.onResolved = [];
self.onRejected = [];
function resolve(value) {
if (self.status === 'pending') {
self.value = value;
self.status = 'resolved';
self.onResolved.forEach(fn => fn());
}
}
function reject(reason) {
if (self.status === 'pending') {
self.reason = reason;
self.status = 'rejected';
self.onRejected.forEach(fn => fn());
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
// 解析不同的promise实现
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循环引用'));
}
let called;
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then; // 如何判断是promise 就判断又没then方法
if (typeof then === 'function') {
then.call(x, (y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, (e) => {
if (called) return;
called = true;
reject(e);
});
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
Promise.prototype.then = function (onfulfilled, onrejected) {
onfulfilled = typeof onfulfilled == 'function' ? onfulfilled : val => val;
onrejected = typeof onrejected === 'function' ? onrejected : err => {
throw err;
}
let self = this;
let promise2;
promise2 = new Promise((resolve, reject) => {
if (self.status === 'resolved') {
setTimeout(() => { // 目的是为了实现异步
try {
let x = onfulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (self.status === 'rejected') {
setTimeout(() => {
try {
let x = onrejected(self.reason);
resolvePromise(promise2, x, resolve, reject); // 解析x 和 promise2的关系
} catch (e) {
reject(e);
}
}, 0);
}
if (self.status === 'pending') {
self.onResolved.push(function () {
setTimeout(() => {
try {
let x = onfulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
self.onRejected.push(function () {
setTimeout(() => {
try {
let x = onrejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
})
return promise2;
}
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
let results = []; let i = 0;
function processData(index, data) {
results[index] = data; // let arr = [] arr[2] = 100
if (++i === promises.length) {
resolve(results);
}
}
for (let i = 0; i < promises.length; i++) {
let p = promises[i];
p.then((data) => { // 成功后把结果和当前索引 关联起来
processData(i, data);
}, reject);
}
})
}
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
let p = promises[i];
p.then(resolve, reject);
}
})
}
Promise.prototype.catch = function (onrejected) {
return this.then(null, onrejected)
}
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
resolve(value);
})
}
module.exports = Promise
转载自:https://juejin.cn/post/7211064454573424697