Skip to content

promise

js
/**
 * 术语
 * “promise” 是一个对象或函数,其 then 方法的行为符合本规范。
 * “thenable” 是定义 then 方法的对象或函数。
 * “value” 是任何合法的 JavaScript 值(包括undefined、thenable 或 promise)。
 * “异常” 是使用 throw 语句抛出的值。
 * “reason” 是一个值,表示承诺被拒绝的原因。
 */

const PENDING = '待定状态';
const RESOLVED = '已完成状态';
const REJECTED = '已拒绝状态';
const noop = (v) => v;
const noopErr = (e) => {
	throw e;
};
const isFn = (v) => typeof v === 'function';
const isObj = (v) => typeof v === 'object';

class Promise {
	constructor(callback) {
		this.value = undefined; // 任何合法的 JavaScript 值(包括undefined、thenable 或 promise)。
		this.reason = undefined; // 一个值,表示承诺被拒绝的原因。
		this.status = PENDING; // 当未决时,承诺:待定
		this.resolvedFnList = []; // 已完成状态的回调函数列表
		this.rejectedFnList = []; // 已拒绝状态的回调函数列表

		const resolve = (value) => {
			if (this.status === PENDING) {
				this.status = RESOLVED;
				this.value = value;
				this.resolvedFnList.forEach((fn) => fn());
			}
		};

		const reject = (reason) => {
			if (this.status === PENDING) {
				this.status = REJECTED;
				this.reason = reason;
				this.rejectedFnList.forEach((fn) => fn());
			}
		};

		try {
			callback(resolve, reject); // 主函数立即执行
		} catch (error) {
			reject(error);
		}
	}
	static resolve(v) {
		return v instanceof Promise ? v : new Promise((res, rej) => res(v));
	}
	static reject(v) {
		return v instanceof Promise ? v : new Promise((res, rej) => rej(v));
	}
	static all(arr) {}
	static race(arr) {}
	then(onResolved, onRejected) {}
	catch(onCatchFn) {
		this.then(undefined, onCatchFn);
	}
	/**
	 * 不管成功还是失败,都会走到 finally 中,
	 * 并且 finally 之后,还可以继续 then。并且会将值原封不动的传递给后面的 then.
	 */
	finally(callback) {
		const resolve = (value) => {
			const res = callback();
			return Promise.resolve(res).then(() => value);
		};
		const reject = (reason) => {
			const res = callback();
			return Promise.resolve(res).then(() => {
				throw reason;
			});
		};
		return this.then(resolve, reject);
	}
}
/**
 * 术语
 * “promise” 是一个对象或函数,其 then 方法的行为符合本规范。
 * “thenable” 是定义 then 方法的对象或函数。
 * “value” 是任何合法的 JavaScript 值(包括undefined、thenable 或 promise)。
 * “异常” 是使用 throw 语句抛出的值。
 * “reason” 是一个值,表示承诺被拒绝的原因。
 */

const PENDING = '待定状态';
const RESOLVED = '已完成状态';
const REJECTED = '已拒绝状态';
const noop = (v) => v;
const noopErr = (e) => {
	throw e;
};
const isFn = (v) => typeof v === 'function';
const isObj = (v) => typeof v === 'object';

class Promise {
	constructor(callback) {
		this.value = undefined; // 任何合法的 JavaScript 值(包括undefined、thenable 或 promise)。
		this.reason = undefined; // 一个值,表示承诺被拒绝的原因。
		this.status = PENDING; // 当未决时,承诺:待定
		this.resolvedFnList = []; // 已完成状态的回调函数列表
		this.rejectedFnList = []; // 已拒绝状态的回调函数列表

		const resolve = (value) => {
			if (this.status === PENDING) {
				this.status = RESOLVED;
				this.value = value;
				this.resolvedFnList.forEach((fn) => fn());
			}
		};

		const reject = (reason) => {
			if (this.status === PENDING) {
				this.status = REJECTED;
				this.reason = reason;
				this.rejectedFnList.forEach((fn) => fn());
			}
		};

		try {
			callback(resolve, reject); // 主函数立即执行
		} catch (error) {
			reject(error);
		}
	}
	static resolve(v) {
		return v instanceof Promise ? v : new Promise((res, rej) => res(v));
	}
	static reject(v) {
		return v instanceof Promise ? v : new Promise((res, rej) => rej(v));
	}
	static all(arr) {}
	static race(arr) {}
	then(onResolved, onRejected) {}
	catch(onCatchFn) {
		this.then(undefined, onCatchFn);
	}
	/**
	 * 不管成功还是失败,都会走到 finally 中,
	 * 并且 finally 之后,还可以继续 then。并且会将值原封不动的传递给后面的 then.
	 */
	finally(callback) {
		const resolve = (value) => {
			const res = callback();
			return Promise.resolve(res).then(() => value);
		};
		const reject = (reason) => {
			const res = callback();
			return Promise.resolve(res).then(() => {
				throw reason;
			});
		};
		return this.then(resolve, reject);
	}
}
js
// Promise.all(iterable)
// Promise.all 等待所有兑现(或第一个拒绝)的结果。

function all(arr = []) {
	return new Promise((resolve, reject) => {
		let resolveList = [];
		let resolveCount = 0;

		function insertResolveList(idx, val) {
			resolveList[idx] = val;
			resolveCount++;
			if (resolveCount === arr.length) resolve(resolveList);
		}

		arr.forEach((obj, idx) => {
			if (obj instanceof Promise) {
				obj.then(
					(val) => insertResolveList(idx, val), // 收集 resolve 结果
					(err) => reject(err) // 直接输出 reject 结果
				);
			} else {
				insertResolveList(idx, val); // 原始值,收集原始值
			}
		});
	});
}
// Promise.all(iterable)
// Promise.all 等待所有兑现(或第一个拒绝)的结果。

function all(arr = []) {
	return new Promise((resolve, reject) => {
		let resolveList = [];
		let resolveCount = 0;

		function insertResolveList(idx, val) {
			resolveList[idx] = val;
			resolveCount++;
			if (resolveCount === arr.length) resolve(resolveList);
		}

		arr.forEach((obj, idx) => {
			if (obj instanceof Promise) {
				obj.then(
					(val) => insertResolveList(idx, val), // 收集 resolve 结果
					(err) => reject(err) // 直接输出 reject 结果
				);
			} else {
				insertResolveList(idx, val); // 原始值,收集原始值
			}
		});
	});
}
js
// Promise.race(iterable)
// Promise.race 等待第一个兑现的结果。

function race(arr) {
	return new Promise((resolve, reject) => {
		// 是否存在 Promise 子项
		let hasPromise = false;

		arr.forEach((obj, idx) => {
			if (obj instanceof Promise) {
				hasPromise = true;
				// 先到先得
				obj.then(resolve, reject);
			}

			// 没有 Promise 子项,返回第一个子项
			if (idx === arr.length - 1 && !hasPromise) {
				resolve(arr[0]);
			}
		});
	});
}
// Promise.race(iterable)
// Promise.race 等待第一个兑现的结果。

function race(arr) {
	return new Promise((resolve, reject) => {
		// 是否存在 Promise 子项
		let hasPromise = false;

		arr.forEach((obj, idx) => {
			if (obj instanceof Promise) {
				hasPromise = true;
				// 先到先得
				obj.then(resolve, reject);
			}

			// 没有 Promise 子项,返回第一个子项
			if (idx === arr.length - 1 && !hasPromise) {
				resolve(arr[0]);
			}
		});
	});
}
js
const noop = (v) => v;
const noopErr = (e) => {
	throw e;
};
const isFn = (v) => typeof v === 'function';
const isObj = (v) => typeof v === 'object';
const PENDING = '待定状态';
const RESOLVED = '已完成状态';
const REJECTED = '已拒绝状态';

function then(onResolved, onRejected) {
	// onResolved 可选,可能是 Promise、fn 等,非函数忽略,使用 noop 函数 向下传递 value
	onResolved = isFn(onResolved) ? onResolved : noop;
	// onRejected 可选,可能是 Promise、fn 等,非函数忽略,使用 noopErr 函数向下传递 reason
	onRejected = isFn(onRejected) ? onRejected : noopErr;
	// 承诺解决程序
	const resolvePromise = (promise2, x, resolve, reject) => {
		// 如果 promise 和 x 引用同一个对象,以 TypeError 为理由拒绝。
		if (promise2 === x) return reject(new TypeError('TypeError'));
		// 2.3.3.3.3 如果同时调用resolvePromise和rejectPromise,或者多次调用同一个参数,则第一个调用优先,任何进一步的调用都将被忽略。
		let called = false;
		// 2.3.3 如果 x 是一个非 null 的对象或函数
		if ((isObj(x) && x !== null) || isFn(x)) {
			try {
				// 3.5
				// 这个首先存储对 的引用x.then,然后测试该引用,然后调用该引用的过程避免了对该x.then属性的多次访问。
				// 这些预防措施对于确保访问器属性的一致性很重要,访问器属性的值可能会在检索之间发生变化。
				let then = x.then;
				if (isFn(then)) {
					then.call(
						x,
						(y) => {
							if (called) return;
							called = true;
							// 递归( 可能promise 嵌套)
							resolvePromise(promise2, y, resolve, reject);
						},
						(z) => {
							if (called) return; // 只要失败就失败
							called = true;
							reject(z);
						}
					);
				} else {
					// 2.3.3.4 如果 then 不是一个函数,用 x 完成 promise。
					resolve(x);
				}
			} catch (e) {
				// 2.3.3.2 抛出的异常的结果 e,e 作为拒绝 promise 的原因。
				if (called) return;
				called = true;
				reject(e);
			}
		} else {
			resolve(x);
		}
	};

	const promise2 = new Promise((resolve, reject) => {
		if (this.status === RESOLVED) {
			queueMicrotask(() => {
				try {
					let x = onResolved(this.value);
					resolvePromise(promise2, x, resolve, reject);
				} catch (e) {
					reject(e);
				}
			});
		}
		if (this.status === REJECTED) {
			queueMicrotask(() => {
				try {
					let x = onRejected(this.reason);
					resolvePromise(promise2, x, resolve, reject);
				} catch (e) {
					reject(e);
				}
			});
		}
		if (this.status === PENDING) {
			this.resolvedFnList.push(() => {
				queueMicrotask(() => {
					try {
						let x = onResolved(this.value);
						resolvePromise(promise2, x, resolve, reject);
					} catch (e) {
						reject(e);
					}
				});
			});
			this.rejectedFnList.push(() => {
				queueMicrotask(() => {
					try {
						let x = onRejected(this.reason);
						resolvePromise(promise2, x, resolve, reject);
					} catch (e) {
						reject(e);
					}
				});
			});
		}
	});
	// 2.2.7 then必须返回一个承诺
	return promise2;
}
const noop = (v) => v;
const noopErr = (e) => {
	throw e;
};
const isFn = (v) => typeof v === 'function';
const isObj = (v) => typeof v === 'object';
const PENDING = '待定状态';
const RESOLVED = '已完成状态';
const REJECTED = '已拒绝状态';

function then(onResolved, onRejected) {
	// onResolved 可选,可能是 Promise、fn 等,非函数忽略,使用 noop 函数 向下传递 value
	onResolved = isFn(onResolved) ? onResolved : noop;
	// onRejected 可选,可能是 Promise、fn 等,非函数忽略,使用 noopErr 函数向下传递 reason
	onRejected = isFn(onRejected) ? onRejected : noopErr;
	// 承诺解决程序
	const resolvePromise = (promise2, x, resolve, reject) => {
		// 如果 promise 和 x 引用同一个对象,以 TypeError 为理由拒绝。
		if (promise2 === x) return reject(new TypeError('TypeError'));
		// 2.3.3.3.3 如果同时调用resolvePromise和rejectPromise,或者多次调用同一个参数,则第一个调用优先,任何进一步的调用都将被忽略。
		let called = false;
		// 2.3.3 如果 x 是一个非 null 的对象或函数
		if ((isObj(x) && x !== null) || isFn(x)) {
			try {
				// 3.5
				// 这个首先存储对 的引用x.then,然后测试该引用,然后调用该引用的过程避免了对该x.then属性的多次访问。
				// 这些预防措施对于确保访问器属性的一致性很重要,访问器属性的值可能会在检索之间发生变化。
				let then = x.then;
				if (isFn(then)) {
					then.call(
						x,
						(y) => {
							if (called) return;
							called = true;
							// 递归( 可能promise 嵌套)
							resolvePromise(promise2, y, resolve, reject);
						},
						(z) => {
							if (called) return; // 只要失败就失败
							called = true;
							reject(z);
						}
					);
				} else {
					// 2.3.3.4 如果 then 不是一个函数,用 x 完成 promise。
					resolve(x);
				}
			} catch (e) {
				// 2.3.3.2 抛出的异常的结果 e,e 作为拒绝 promise 的原因。
				if (called) return;
				called = true;
				reject(e);
			}
		} else {
			resolve(x);
		}
	};

	const promise2 = new Promise((resolve, reject) => {
		if (this.status === RESOLVED) {
			queueMicrotask(() => {
				try {
					let x = onResolved(this.value);
					resolvePromise(promise2, x, resolve, reject);
				} catch (e) {
					reject(e);
				}
			});
		}
		if (this.status === REJECTED) {
			queueMicrotask(() => {
				try {
					let x = onRejected(this.reason);
					resolvePromise(promise2, x, resolve, reject);
				} catch (e) {
					reject(e);
				}
			});
		}
		if (this.status === PENDING) {
			this.resolvedFnList.push(() => {
				queueMicrotask(() => {
					try {
						let x = onResolved(this.value);
						resolvePromise(promise2, x, resolve, reject);
					} catch (e) {
						reject(e);
					}
				});
			});
			this.rejectedFnList.push(() => {
				queueMicrotask(() => {
					try {
						let x = onRejected(this.reason);
						resolvePromise(promise2, x, resolve, reject);
					} catch (e) {
						reject(e);
					}
				});
			});
		}
	});
	// 2.2.7 then必须返回一个承诺
	return promise2;
}
js
/**
 * 术语
 * “promise” 是一个对象或函数,其 then 方法的行为符合本规范。
 * “thenable” 是定义 then 方法的对象或函数。
 * “value” 是任何合法的 JavaScript 值(包括undefined、thenable 或 promise)。
 * “异常” 是使用 throw 语句抛出的值。
 * “reason” 是一个值,表示承诺被拒绝的原因。
 */

const PENDING = '待定状态';
const RESOLVED = '已完成状态';
const REJECTED = '已拒绝状态';
const noop = (v) => v;
const noopErr = (e) => {
	throw e;
};
const isFn = (v) => typeof v === 'function';
const isObj = (v) => typeof v === 'object';

class Promise {
	constructor(callback) {
		this.value = undefined; // 任何合法的 JavaScript 值(包括undefined、thenable 或 promise)。
		this.reason = undefined; // 一个值,表示承诺被拒绝的原因。
		this.status = PENDING; // 当未决时,承诺:待定
		this.resolvedFnList = []; // 已完成状态的回调函数列表
		this.rejectedFnList = []; // 已拒绝状态的回调函数列表
		const resolve = (value) => {
			// 2.1.1.1 可以转换到已完成或拒绝状态。
			// 2.1.2.1 实现时,承诺:不得过渡到任何其他状态。
			if (this.status === PENDING) {
				this.status = RESOLVED;
				this.value = value;
				this.resolvedFnList.forEach((fn) => fn());
			}
		};
		const reject = (reason) => {
			// 2.1.1.1 可以转换到已完成或拒绝状态。
			// 2.1.3.1 当被拒绝时,一个承诺:不得过渡到任何其他状态。
			if (this.status === PENDING) {
				this.status = REJECTED;
				this.reason = reason;
				this.rejectedFnList.forEach((fn) => fn());
			}
		};
		try {
			callback(resolve, reject); // 主函数立即执行
		} catch (error) {
			reject(error);
		}
	}
	/**
	 * 承诺必须提供一种then方法来访问其当前或最终值或原因。
	 * 一个 promise 的then方法接受两个参数:onResolve onRejected
	 * 2.2.1 这两个 onResolved 和 onRejected 可选的参数:
	 *      2.2.1.1 如果 onResolved 不是函数,则必须忽略它。
	 *      2.2.1.2 如果 onRejected 不是函数,则必须忽略它。
	 *
	 * 始终返回一个 Promise 对象
	 * onResolved 可选,可能是 Promise、fn 等,非函数忽略,使用 noop 函数 向下传递 value
	 * onRejected 可选,可能是 Promise、fn 等,非函数忽略,使用 noopErr 函数向下传递 reason
	 *      (先抛出 err,后续捕获 err,如果没有捕获到,最终抛出 err)
	 * then 可以链式调用,可以多次调用
	 * 当已拒绝状态时,没有找到处理拒绝状态的回调函数前都是已拒绝状态,找到后返回的新的 Promise 对象为已完成状态。
	 */
	then(onResolved, onRejected) {
		// onResolved 可选,可能是 Promise、fn 等,非函数忽略,使用 noop 函数 向下传递 value
		onResolved = isFn(onResolved) ? onResolved : noop;
		// onRejected 可选,可能是 Promise、fn 等,非函数忽略,使用 noopErr 函数向下传递 reason
		onRejected = isFn(onRejected) ? onRejected : noopErr;
		// 承诺解决程序
		const resolvePromise = (promise2, x, resolve, reject) => {
			// 如果 promise 和 x 引用同一个对象,以 TypeError 为理由拒绝。
			if (promise2 === x) return reject(new TypeError('TypeError'));
			// 2.3.3.3.3 如果同时调用resolvePromise和rejectPromise,或者多次调用同一个参数,则第一个调用优先,任何进一步的调用都将被忽略。
			let called = false;
			// 2.3.3 如果 x 是一个非 null 的对象或函数
			if ((isObj(x) && x !== null) || isFn(x)) {
				try {
					// 3.5
					// 这个首先存储对 的引用x.then,然后测试该引用,然后调用该引用的过程避免了对该x.then属性的多次访问。
					// 这些预防措施对于确保访问器属性的一致性很重要,访问器属性的值可能会在检索之间发生变化。
					let then = x.then;
					if (isFn(then)) {
						then.call(
							x,
							(y) => {
								if (called) return;
								called = true;
								// 递归( 可能promise 嵌套)
								resolvePromise(promise2, y, resolve, reject);
							},
							(z) => {
								if (called) return; // 只要失败就失败
								called = true;
								reject(z);
							}
						);
					} else {
						// 2.3.3.4 如果 then 不是一个函数,用 x 完成 promise。
						resolve(x);
					}
				} catch (e) {
					// 2.3.3.2 抛出的异常的结果 e,e 作为拒绝 promise 的原因。
					if (called) return;
					called = true;
					reject(e);
				}
			} else {
				resolve(x);
			}
		};
		const promise2 = new Promise((resolve, reject) => {
			if (this.status === RESOLVED) {
				setTimeout(() => {
					try {
						let x = onResolved(this.value);
						resolvePromise(promise2, x, resolve, reject);
					} catch (e) {
						reject(e);
					}
				}, 0);
			}
			if (this.status === REJECTED) {
				setTimeout(() => {
					try {
						let x = onRejected(this.reason);
						resolvePromise(promise2, x, resolve, reject);
					} catch (e) {
						reject(e);
					}
				}, 0);
			}
			if (this.status === PENDING) {
				this.resolvedFnList.push(() => {
					setTimeout(() => {
						try {
							let x = onResolved(this.value);
							resolvePromise(promise2, x, resolve, reject);
						} catch (e) {
							reject(e);
						}
					}, 0);
				});
				this.rejectedFnList.push(() => {
					setTimeout(() => {
						try {
							let x = onRejected(this.reason);
							resolvePromise(promise2, x, resolve, reject);
						} catch (e) {
							reject(e);
						}
					}, 0);
				});
			}
		});
		// 2.2.7 then必须返回一个承诺
		return promise2;
	}
	/**
	 * resolve 静态方法,返回一个已完成 Promise 对象
	 * resolve 可以没有接收函数,不报错
	 */
	static resolve(v) {
		return v instanceof Promise ? v : new Promise((res, rej) => res(v));
	}
	/**
	 * reject 静态方法,返回一个已拒绝 Promise 对象
	 * reject 返回的一个已拒绝 Promise 对象,必须要找到处理方法(catch() 或者 then.onRejected()),否则报错
	 */
	static reject(v) {
		return v instanceof Promise ? v : new Promise((res, rej) => rej(v));
	}
	/**
	 * all 方法是一个静态方法
	 * all 方法返回一个Promise对象
	 * all 方法传入的是一个带有 Promise 对象的数组
	 * 只有数组中的 Promise 对象都成功执行,才能回调成功方法
	 * 如果有 Promise 对象失败,则调用失败方法
	 */
	static all(arr) {
		return new Promise((resolve, reject) => {
			const resultArr = [];
			let count = 0;
			function insertArr(idx, val) {
				resultArr[idx] = val;
				count++;
				if (count === arr.length) resolve(resultArr);
			}
			arr.forEach((obj, idx) => {
				if (obj instanceof Promise) {
					obj.then(
						(val) => insertArr(idx, val),
						(err) => reject(err)
					);
				} else {
					insertArr(idx, val);
				}
			});
		});
	}
	/**
	 * race 方法传入 Promise 对象数组。
	 * race 只返回执行最快的一个 Promise 结果,不论成功与失败。
	 * 返回结果与最快的 Promise 的成功与失败保持一致。
	 * 如果数组不包含 Promise 对象,返回数组第一项
	 */
	static race(arr) {
		return new Promise((resolve, reject) => {
			let hasPromise = false;
			arr.forEach((obj, idx) => {
				if (obj instanceof Promise) {
					hasPromise = true;
					obj.then(resolve, reject);
				}
				if (idx === arr.length - 1 && !hasPromise) {
					resolve(arr[0]);
				}
			});
		});
	}
	/**
	 * 不管成功还是失败,都会走到 finally 中,
	 * 并且 finally 之后,还可以继续 then。并且会将值原封不动的传递给后面的 then.
	 */
	finally(callback) {
		return this.then(
			(value) => {
				return Promise.resolve(callback()).then(() => {
					return value;
				});
			},
			(reason) => {
				return Promise.resolve(callback()).then(() => {
					throw reason;
				});
			}
		);
	}
	/**
	 * catch 是一个 then 的已拒绝状态。
	 * catch 不能想 then 一样自动接受 Promise 对象的状态
	 * catch 接受异常错误和未处理过的拒绝状态的返回数据
	 */
	catch(onCatchFn) {
		this.then(undefined, onCatchFn);
	}
}
// Promise/A+规范提供了一个专门的测试脚本,可以测试所编写的代码是否符合Promise/A+的规范。
// 首先,在 promise2 实现的代码中,增加以下代码:
Promise.defer = Promise.deferred = function () {
	let dfd = {};
	dfd.promise = new Promise((resolve, reject) => {
		dfd.resolve = resolve;
		dfd.reject = reject;
	});
	return dfd;
};

// module.exports = Promise;

/**
 * 测试方法 (测试范围不包括 Promise 方法)
 * > npm i -g promises-aplus-tests
 * > promises-aplus-tests demo.js
 *
 * 测试结果:872 passing (17s)
 */
/**
 * 术语
 * “promise” 是一个对象或函数,其 then 方法的行为符合本规范。
 * “thenable” 是定义 then 方法的对象或函数。
 * “value” 是任何合法的 JavaScript 值(包括undefined、thenable 或 promise)。
 * “异常” 是使用 throw 语句抛出的值。
 * “reason” 是一个值,表示承诺被拒绝的原因。
 */

const PENDING = '待定状态';
const RESOLVED = '已完成状态';
const REJECTED = '已拒绝状态';
const noop = (v) => v;
const noopErr = (e) => {
	throw e;
};
const isFn = (v) => typeof v === 'function';
const isObj = (v) => typeof v === 'object';

class Promise {
	constructor(callback) {
		this.value = undefined; // 任何合法的 JavaScript 值(包括undefined、thenable 或 promise)。
		this.reason = undefined; // 一个值,表示承诺被拒绝的原因。
		this.status = PENDING; // 当未决时,承诺:待定
		this.resolvedFnList = []; // 已完成状态的回调函数列表
		this.rejectedFnList = []; // 已拒绝状态的回调函数列表
		const resolve = (value) => {
			// 2.1.1.1 可以转换到已完成或拒绝状态。
			// 2.1.2.1 实现时,承诺:不得过渡到任何其他状态。
			if (this.status === PENDING) {
				this.status = RESOLVED;
				this.value = value;
				this.resolvedFnList.forEach((fn) => fn());
			}
		};
		const reject = (reason) => {
			// 2.1.1.1 可以转换到已完成或拒绝状态。
			// 2.1.3.1 当被拒绝时,一个承诺:不得过渡到任何其他状态。
			if (this.status === PENDING) {
				this.status = REJECTED;
				this.reason = reason;
				this.rejectedFnList.forEach((fn) => fn());
			}
		};
		try {
			callback(resolve, reject); // 主函数立即执行
		} catch (error) {
			reject(error);
		}
	}
	/**
	 * 承诺必须提供一种then方法来访问其当前或最终值或原因。
	 * 一个 promise 的then方法接受两个参数:onResolve onRejected
	 * 2.2.1 这两个 onResolved 和 onRejected 可选的参数:
	 *      2.2.1.1 如果 onResolved 不是函数,则必须忽略它。
	 *      2.2.1.2 如果 onRejected 不是函数,则必须忽略它。
	 *
	 * 始终返回一个 Promise 对象
	 * onResolved 可选,可能是 Promise、fn 等,非函数忽略,使用 noop 函数 向下传递 value
	 * onRejected 可选,可能是 Promise、fn 等,非函数忽略,使用 noopErr 函数向下传递 reason
	 *      (先抛出 err,后续捕获 err,如果没有捕获到,最终抛出 err)
	 * then 可以链式调用,可以多次调用
	 * 当已拒绝状态时,没有找到处理拒绝状态的回调函数前都是已拒绝状态,找到后返回的新的 Promise 对象为已完成状态。
	 */
	then(onResolved, onRejected) {
		// onResolved 可选,可能是 Promise、fn 等,非函数忽略,使用 noop 函数 向下传递 value
		onResolved = isFn(onResolved) ? onResolved : noop;
		// onRejected 可选,可能是 Promise、fn 等,非函数忽略,使用 noopErr 函数向下传递 reason
		onRejected = isFn(onRejected) ? onRejected : noopErr;
		// 承诺解决程序
		const resolvePromise = (promise2, x, resolve, reject) => {
			// 如果 promise 和 x 引用同一个对象,以 TypeError 为理由拒绝。
			if (promise2 === x) return reject(new TypeError('TypeError'));
			// 2.3.3.3.3 如果同时调用resolvePromise和rejectPromise,或者多次调用同一个参数,则第一个调用优先,任何进一步的调用都将被忽略。
			let called = false;
			// 2.3.3 如果 x 是一个非 null 的对象或函数
			if ((isObj(x) && x !== null) || isFn(x)) {
				try {
					// 3.5
					// 这个首先存储对 的引用x.then,然后测试该引用,然后调用该引用的过程避免了对该x.then属性的多次访问。
					// 这些预防措施对于确保访问器属性的一致性很重要,访问器属性的值可能会在检索之间发生变化。
					let then = x.then;
					if (isFn(then)) {
						then.call(
							x,
							(y) => {
								if (called) return;
								called = true;
								// 递归( 可能promise 嵌套)
								resolvePromise(promise2, y, resolve, reject);
							},
							(z) => {
								if (called) return; // 只要失败就失败
								called = true;
								reject(z);
							}
						);
					} else {
						// 2.3.3.4 如果 then 不是一个函数,用 x 完成 promise。
						resolve(x);
					}
				} catch (e) {
					// 2.3.3.2 抛出的异常的结果 e,e 作为拒绝 promise 的原因。
					if (called) return;
					called = true;
					reject(e);
				}
			} else {
				resolve(x);
			}
		};
		const promise2 = new Promise((resolve, reject) => {
			if (this.status === RESOLVED) {
				setTimeout(() => {
					try {
						let x = onResolved(this.value);
						resolvePromise(promise2, x, resolve, reject);
					} catch (e) {
						reject(e);
					}
				}, 0);
			}
			if (this.status === REJECTED) {
				setTimeout(() => {
					try {
						let x = onRejected(this.reason);
						resolvePromise(promise2, x, resolve, reject);
					} catch (e) {
						reject(e);
					}
				}, 0);
			}
			if (this.status === PENDING) {
				this.resolvedFnList.push(() => {
					setTimeout(() => {
						try {
							let x = onResolved(this.value);
							resolvePromise(promise2, x, resolve, reject);
						} catch (e) {
							reject(e);
						}
					}, 0);
				});
				this.rejectedFnList.push(() => {
					setTimeout(() => {
						try {
							let x = onRejected(this.reason);
							resolvePromise(promise2, x, resolve, reject);
						} catch (e) {
							reject(e);
						}
					}, 0);
				});
			}
		});
		// 2.2.7 then必须返回一个承诺
		return promise2;
	}
	/**
	 * resolve 静态方法,返回一个已完成 Promise 对象
	 * resolve 可以没有接收函数,不报错
	 */
	static resolve(v) {
		return v instanceof Promise ? v : new Promise((res, rej) => res(v));
	}
	/**
	 * reject 静态方法,返回一个已拒绝 Promise 对象
	 * reject 返回的一个已拒绝 Promise 对象,必须要找到处理方法(catch() 或者 then.onRejected()),否则报错
	 */
	static reject(v) {
		return v instanceof Promise ? v : new Promise((res, rej) => rej(v));
	}
	/**
	 * all 方法是一个静态方法
	 * all 方法返回一个Promise对象
	 * all 方法传入的是一个带有 Promise 对象的数组
	 * 只有数组中的 Promise 对象都成功执行,才能回调成功方法
	 * 如果有 Promise 对象失败,则调用失败方法
	 */
	static all(arr) {
		return new Promise((resolve, reject) => {
			const resultArr = [];
			let count = 0;
			function insertArr(idx, val) {
				resultArr[idx] = val;
				count++;
				if (count === arr.length) resolve(resultArr);
			}
			arr.forEach((obj, idx) => {
				if (obj instanceof Promise) {
					obj.then(
						(val) => insertArr(idx, val),
						(err) => reject(err)
					);
				} else {
					insertArr(idx, val);
				}
			});
		});
	}
	/**
	 * race 方法传入 Promise 对象数组。
	 * race 只返回执行最快的一个 Promise 结果,不论成功与失败。
	 * 返回结果与最快的 Promise 的成功与失败保持一致。
	 * 如果数组不包含 Promise 对象,返回数组第一项
	 */
	static race(arr) {
		return new Promise((resolve, reject) => {
			let hasPromise = false;
			arr.forEach((obj, idx) => {
				if (obj instanceof Promise) {
					hasPromise = true;
					obj.then(resolve, reject);
				}
				if (idx === arr.length - 1 && !hasPromise) {
					resolve(arr[0]);
				}
			});
		});
	}
	/**
	 * 不管成功还是失败,都会走到 finally 中,
	 * 并且 finally 之后,还可以继续 then。并且会将值原封不动的传递给后面的 then.
	 */
	finally(callback) {
		return this.then(
			(value) => {
				return Promise.resolve(callback()).then(() => {
					return value;
				});
			},
			(reason) => {
				return Promise.resolve(callback()).then(() => {
					throw reason;
				});
			}
		);
	}
	/**
	 * catch 是一个 then 的已拒绝状态。
	 * catch 不能想 then 一样自动接受 Promise 对象的状态
	 * catch 接受异常错误和未处理过的拒绝状态的返回数据
	 */
	catch(onCatchFn) {
		this.then(undefined, onCatchFn);
	}
}
// Promise/A+规范提供了一个专门的测试脚本,可以测试所编写的代码是否符合Promise/A+的规范。
// 首先,在 promise2 实现的代码中,增加以下代码:
Promise.defer = Promise.deferred = function () {
	let dfd = {};
	dfd.promise = new Promise((resolve, reject) => {
		dfd.resolve = resolve;
		dfd.reject = reject;
	});
	return dfd;
};

// module.exports = Promise;

/**
 * 测试方法 (测试范围不包括 Promise 方法)
 * > npm i -g promises-aplus-tests
 * > promises-aplus-tests demo.js
 *
 * 测试结果:872 passing (17s)
 */
js
// 并发请求限制

function limitRequst(list, limit) {
	// 返回一个 Promise
	return new Promise((resolve) => {
		let pending = 0; // 待定状态任务数量
		let resultList = new Array(list.length); // 任务结果
		let taskList = list.map((task, index) => ({ index, task })); // 任务列表(记录任务索引,用以保证任务结果顺序)

		request();

		function request() {
			const subList = taskList.splice(0, limit - pending); // 提取待处理任务
			const subListPatched = patch(subList); // 修补待处理任务
			pending += subListPatched.length; // 更新待定状态任务数量
			// 并发任务
			Promise.allSettled(subListPatched).then((resList) => {
				// 收集任务结果 (保持原始顺序)
				resList.forEach((res, idx) => {
					const index = subList[idx].index;
					resultList[index] = res;
				});
				// 结果全部完成判定,并返回任务结果
				if (!resultList.includes(undefined)) {
					resolve(resultList);
				}
			});
		}

		// 修补待处理任务
		function patch(list = []) {
			return list.map(({ task }) => {
				// 非正常任务修补
				if (task instanceof Promise === false) {
					task = Promise.resolve(task); // 修补
				}
				// 捕获单任务的最终状态
				task.finally(() => {
					pending--; // 更新待定状态任务数量
					request(); // 处理剩余任务
				}).catch(() => {
					// 您的 Promise 必须自己处理 catch 情况,
					// 此处 catch 只是为了保证方法能正常运行,但对 catch 结果不做处理。
				});
				return task;
			});
		}
	});
}

function createPromise() {
	return new Promise((resolve, reject) => {
		if (Math.random() > 0.5) {
			setTimeout(() => {
				resolve('resolve');
			}, 500);
		} else {
			setTimeout(() => {
				reject(new Error('reject'));
			}, 500);
		}
	});
}

const list = [createPromise(), createPromise(), 1, createPromise(), createPromise(), null];

limitRequst(list, 3).then((list) => {
	console.log('list', list.length, list);
});

// 控制台输出:
// list 6 [
//     { status: 'fulfilled', value: 'resolve' },
//     {
//       status: 'rejected',
//       reason: Error: reject
//           at Timeout._onTimeout (/Users/pch/Documents/GitHub/test.js:65:24)
//           at listOnTimeout (node:internal/timers:559:17)
//           at processTimers (node:internal/timers:502:7)
//     },
//     { status: 'fulfilled', value: 1 },
//     { status: 'fulfilled', value: 'resolve' },
//     {
//       status: 'rejected',
//       reason: Error: reject
//           at Timeout._onTimeout (/Users/pch/Documents/GitHub/test.js:65:24)
//           at listOnTimeout (node:internal/timers:559:17)
//           at processTimers (node:internal/timers:502:7)
//     },
//     { status: 'fulfilled', value: null }
//   ]
// 并发请求限制

function limitRequst(list, limit) {
	// 返回一个 Promise
	return new Promise((resolve) => {
		let pending = 0; // 待定状态任务数量
		let resultList = new Array(list.length); // 任务结果
		let taskList = list.map((task, index) => ({ index, task })); // 任务列表(记录任务索引,用以保证任务结果顺序)

		request();

		function request() {
			const subList = taskList.splice(0, limit - pending); // 提取待处理任务
			const subListPatched = patch(subList); // 修补待处理任务
			pending += subListPatched.length; // 更新待定状态任务数量
			// 并发任务
			Promise.allSettled(subListPatched).then((resList) => {
				// 收集任务结果 (保持原始顺序)
				resList.forEach((res, idx) => {
					const index = subList[idx].index;
					resultList[index] = res;
				});
				// 结果全部完成判定,并返回任务结果
				if (!resultList.includes(undefined)) {
					resolve(resultList);
				}
			});
		}

		// 修补待处理任务
		function patch(list = []) {
			return list.map(({ task }) => {
				// 非正常任务修补
				if (task instanceof Promise === false) {
					task = Promise.resolve(task); // 修补
				}
				// 捕获单任务的最终状态
				task.finally(() => {
					pending--; // 更新待定状态任务数量
					request(); // 处理剩余任务
				}).catch(() => {
					// 您的 Promise 必须自己处理 catch 情况,
					// 此处 catch 只是为了保证方法能正常运行,但对 catch 结果不做处理。
				});
				return task;
			});
		}
	});
}

function createPromise() {
	return new Promise((resolve, reject) => {
		if (Math.random() > 0.5) {
			setTimeout(() => {
				resolve('resolve');
			}, 500);
		} else {
			setTimeout(() => {
				reject(new Error('reject'));
			}, 500);
		}
	});
}

const list = [createPromise(), createPromise(), 1, createPromise(), createPromise(), null];

limitRequst(list, 3).then((list) => {
	console.log('list', list.length, list);
});

// 控制台输出:
// list 6 [
//     { status: 'fulfilled', value: 'resolve' },
//     {
//       status: 'rejected',
//       reason: Error: reject
//           at Timeout._onTimeout (/Users/pch/Documents/GitHub/test.js:65:24)
//           at listOnTimeout (node:internal/timers:559:17)
//           at processTimers (node:internal/timers:502:7)
//     },
//     { status: 'fulfilled', value: 1 },
//     { status: 'fulfilled', value: 'resolve' },
//     {
//       status: 'rejected',
//       reason: Error: reject
//           at Timeout._onTimeout (/Users/pch/Documents/GitHub/test.js:65:24)
//           at listOnTimeout (node:internal/timers:559:17)
//           at processTimers (node:internal/timers:502:7)
//     },
//     { status: 'fulfilled', value: null }
//   ]

༼ つ/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿◕ _◕ ༽つ/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿ ̿̿