前言
Promise
是 js
异步编程的核心概念之一,它为我们提供了一种更优雅的方式来处理异步操作。
本文将全面剖析 Promise
的工作原理,并逐步实现一个符合 Promise/A+
规范的 Promise 库
。
正文
一、Promise 基础概念
Promise
代表一个异步操作的最终完成(或失败)及其结果值。它有三
种状态:
- pending :
初始状态
,既不是成功,也不是失败状态 - fulfilled :意味着操作
成功
完成 - rejected :意味着操作
失败
状态一旦改变就不能再变,只能从 pending
变为 fulfilled
,或从 pending
变为 rejected
。
二、Promise 核心静态方法实现
1. Promise.resolve 实现
Promise.resolve
方法返回
一个以给定值解析后的 Promise 对象
。
javascript
Promise.resolve = (param) => {
if(param instanceof Promise) return param;
return new Promise((resolve, reject) => {
if(param && param.then && typeof param.then === 'function') {
// param 状态变为成功会调用resolve,将新 Promise 的状态变为成功,反之亦然
param.then(resolve, reject);
}else {
resolve(param);
}
})
}
实现要点:
- 如果
参数
是Promise 实例
,直接返回该实例
- 如果
参数
是 thenable 对象(具有 then 方法的对象
),返回的 Promise 会跟随这个对象` 其他
情况返回一个以该值为成功状态的 Promise 对象
2. Promise.reject 实现
Promise.reject
方法返回一个带有拒绝原因
的 Promise 对象
。
javascript
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
与 resolve 不同,reject 会原封不动
地将 reason 向下传递
。
三、Promise 实例方法实现
1. Promise.prototype.finally 实现
finally
方法无论 Promise 最终状态如何都会执行。
javascript
Promise.prototype.finally = function(callback) {
this.then(value => {
return Promise.resolve(callback()).then(() => {
return value;
})
}, error => {
return Promise.resolve(callback()).then(() => {
throw error;
})
})
}
实现要点:
- 无论
成功或失败
都会执行回调
- 保持原
Promise
的值
向下传
递 - 回调函数返回的
Promise
会等待执行完毕
2. Promise.prototype.then 实现
then
方法是 Promise
的核心,它返回一个新的 Promise
。
javascript
MyPromise.prototype.then = function (onResolved, onRejected) {
var self = this;
var promise2;
// onResolved 和 onRejected 都是可选的
onResolved = typeof onResolved === 'function' ? onResolved : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r };
if (self.currentState === RESOLVED) {
return (promise2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
try {
var x = onResolved(self.value);
resolutionProcedure(promise2, x, resolve, reject);
} catch (reason) {
reject(reason);
}
});
}));
}
// 其他状态类似处理...
}
四、Promise 高级静态方法实现
1. Promise.all 实现
Promise.all
接收一个 Promise 数组
,当所有 Promise 都成功时
返回结果数组,有一个失败则立即失败
。
javascript
Promise.all = function(promises) {
return new Promise((resolve, reject) => {
let result = [];
let index = 0;
let len = promises.length;
if(len === 0) {
resolve(result);
return;
}
for(let i = 0; i < len; i++) {
Promise.resolve(promises[i]).then(data => {
result[i] = data;
index++;
if(index === len) resolve(result);
}).catch(err => {
reject(err);
})
}
})
}
2. Promise.race 实现
Promise.race
返回第一个完成的 Promise
的结果。
javascript
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
let len = promises.length;
if(len === 0) return;
for(let i = 0; i < len; i++) {
Promise.resolve(promises[i]).then(data => {
resolve(data);
return;
}).catch(err => {
reject(err);
return;
})
}
})
}
3. Promise.allSettled 实现
Promise.allSettled
等待所有 Promise 完成
,无论成功或失败
。
javascript
function allSettled(iterable) {
return new Promise((resolve, reject) => {
function addElementToResult(i, elem) {
result[i] = elem;
elementCount++;
if (elementCount === result.length) {
resolve(result);
}
}
let index = 0;
for (const promise of iterable) {
const currentIndex = index;
promise.then(
(value) => addElementToResult(
currentIndex, {
status: 'fulfilled',
value
}),
(reason) => addElementToResult(
currentIndex, {
status: 'rejected',
reason
}));
index++;
}
if (index === 0) {
resolve([]);
return;
}
let elementCount = 0;
const result = new Array(index);
});
}
代码:完整 Promise 实现
下面是一个符合 Promise/A+ 规范的完整实现:
javascript
// 三种状态
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";
function MyPromise(fn) {
let _this = this;
_this.currentState = PENDING;
_this.value = undefined;
_this.resolvedCallbacks = [];
_this.rejectedCallbacks = [];
_this.resolve = function (value) {
if (value instanceof MyPromise) {
return value.then(_this.resolve, _this.reject)
}
setTimeout(() => {
if (_this.currentState === PENDING) {
_this.currentState = RESOLVED;
_this.value = value;
_this.resolvedCallbacks.forEach(cb => cb());
}
})
};
_this.reject = function (reason) {
setTimeout(() => {
if (_this.currentState === PENDING) {
_this.currentState = REJECTED;
_this.value = reason;
_this.rejectedCallbacks.forEach(cb => cb());
}
})
}
try {
fn(_this.resolve, _this.reject);
} catch (e) {
_this.reject(e);
}
}
// then 方法实现
MyPromise.prototype.then = function (onResolved, onRejected) {
var self = this;
var promise2;
onResolved = typeof onResolved === 'function' ? onResolved : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r };
if (self.currentState === RESOLVED) {
return (promise2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
try {
var x = onResolved(self.value);
resolutionProcedure(promise2, x, resolve, reject);
} catch (reason) {
reject(reason);
}
});
}));
}
// 其他状态处理...
};
// 解析过程
function resolutionProcedure(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError("Error"));
}
if (x instanceof MyPromise) {
if (x.currentState === PENDING) {
x.then(function (value) {
resolutionProcedure(promise2, value, resolve, reject);
}, reject);
} else {
x.then(resolve, reject);
}
return;
}
let called = false;
if (x !== null && (typeof x === "object" || typeof x === "function")) {
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
y => {
if (called) return;
called = true;
resolutionProcedure(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 的状态一旦改变就不能再变
- 异步执行:then 方法的回调需要异步执行
- 链式调用:then 方法必须返回一个新的 Promise
- 值穿透:then 的参数如果不是函数需要忽略
- Promise 解析过程:处理 thenable 对象和循环引用
总结
Promise 的核心在于状态管理
、链式调用
和异步处理
。
了解其底层原理,将使我们能够更好地使用和调试Promise代码
,去运用一些第三方Promise库。