Promise-最全最完整的实现

237 阅读4分钟
  • 掘金已经有很多的Promise实现代码了,本人结合了下大佬们的代码基本完善了。

人不狠话不多直接上代码

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>promise的实现</title>
</head>

<body>

</body>

</html>
<script>
	//定义三种状态

	const PENDING = "pending";
	const FULFILLED = "fulfilled";
	const REJECTED = "rejected";
	const resolvePromise = (bridgePromise, x, resolve, reject) => {
		if (x === bridgePromise) {// 循环引用情况
			throw new TypeError('Chaining cycle detected for promise #<Promise>');
		}
		let called = false; // 表示是否调用成功or失败
		// 判断x是否是一个promise的办法:
		// 1.判断是否是对象或者function
		// 2.判断是否有then,并且then是一个方法
		if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
			try {// 考虑一种很极端的情况,即then属性的getter方法内抛出异常,就是一取x.then就报错
				// 是否是thenable对象(具有then方法的对象/函数)
				let then = x.then
				if (typeof then === 'function') {//此时是一个promise
					then.call(x, y => {
						// 防止多次调用
						if (called) return false
						called = true
						// y可能还是个promise,所以递归继续解析直到返回一个普通值
						resolvePromise(bridgePromise, y, resolve, reject);
					}, e => {
						if (called) return false
						called = true
						reject(e)
					})
				} else {// 说明是一个普通对象/函数,直接返回
					resolve(x)
				}
			} catch (error) {
				if (called) return false
				called = true
				reject(error)
			}
		} else {
			resolve(x)
		}
	}
	const gen = (len, resolve) => {
		let values = [], count = 0;
		return (value, i) => {
			values[i] = value
			if (++count === len) {
				resolve(values)
			}
		}
	}
	class PromiseA {
		constructor(executor) {
			if (typeof this !== 'object') {// Promise 必须是new 创建出来的
				throw new TypeError('PromiseA must be constructed via new')
			}
			if (typeof executor !== 'function') { // Promise 的参数必须是function
				throw new TypeError('PromiseA constructor\'s arguments is not a function')
			}
			this.status = PENDING	 // 默认的状态,pending->fulfilled, pending->rejected
			this.value = undefined // 成功的值
			this.error = undefined // 失败的原因
			this.onFulfilledCallbacks = []	// 存放then成功的回调
			this.onRejectedCallbacks = []		// 存放then失败的回调
			try {
				executor(this.resolve.bind(this), this.reject.bind(this)) //new 的时候执行传递resolve和reject函数
			} catch (error) {
				this.reject(error)
			}
			// 同步执行resolve,reject,then
			// PENDING 时候 then onFulfilled和onRejected列表 中 push 回调函数onFulfilled,onRejected
			// resolve setTimeout执行晚于 then 此时 再改变 status状态 并且循环执行onFulfilled和onRejected列表
		}
		static resolve(value) {
			// PromiseA.all
			return new PromiseA((resolve, reject) => {
				resolve(value)
			})
		}
		static resolve(error) {
			// PromiseA.resolve
			return new PromiseA((resolve, reject) => {
				reject(error)
			})
		}
		static all(promiseList) {
			// PromiseA.all
			return new PromiseA((resolve, reject) => {
				let done = gen(promises.length, resolve);
				//利用闭包多次执行后,等promises都完成后resolve
				promiseList.forEach((promise, i) => {
					promise.then((value) => {
						done(value, i)
					}, e => {
						reject(e)
					})
				})
			})
		}
		static race(promiseList) {
			// PromiseA.race
			return new PromiseA((resolve, reject) => {
				promiseList.forEach((promise) => {
					promise.then(resolve, reject)
				})
			})
		}
		static deferred() {//为了通过测试
			let def = {};
			def.promise = new PromiseA(function (resolve, reject) {
				def.resolve = resolve;
				def.reject = reject;
			});
			return def;
		}
		resolve(value) {
			setTimeout(() => {//防止没有异步操作
				if (this.status === PENDING) {
					this.status = FULFILLED
					this.value = value
					this.onFulfilledCallbacks.forEach((cb) => cb(this.value))
				}
			});
		}
		reject(error) {
			setTimeout(() => {
				if (this.status === PENDING) {
					this.status = REJECTED
					this.error = error
					this.onRejectedCallbacks.forEach((cb) => cb(this.error))
				}
			});
		}
		then(onFulfilled, onRejected) {
			//在then中什么都不传的情况,还能继续继续链式调用则判断onFulfilled和onRejected
			onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
			onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };

			let bridgePromise = new PromiseA((resolve, reject) => {
				if (this.status === FULFILLED) {
					// 当成功或失败执行时,有异常那么返回的promise应该处于失败态
					// 用try/catch来防止返回异常的情况
					// 加上setTimeout实现异步调用
					setTimeout(() => {
						try {
							// x可能是个普通值,也可能是个promise
							let x = onFulfilled(this.value);
							resolvePromise(bridgePromise, x, resolve, reject);
						} catch (err) {
							reject(err)
						}
					})
				}
				if (this.status === REJECTED) {
					setTimeout(() => {
						try {
							let x = onRejected(this.error);
							resolvePromise(bridgePromise, x, resolve, reject);
						} catch (err) {
							reject(err);
						}
					})
				}
				// 当promise的执行器中有异步代码的时候,并且触发状态改变的resolve或者reject
				// 在异步代码块中。这种情况下,由于先执行了then,而promise的状态还是PENDING状态
				// 所以then方法内的函数便无法执行。
				// 此时可先将then方法内的函数参数存储起来,利用订阅-发布模式,当执行器中等的异步代码
				// 执行后,触发存储起来的函数的执行。

				if (this.status === PENDING) {
					console.log('1---- then ' + this.status);
					// 当调用then时 可能没成功也没失败,就处于pending状态
					this.onFulfilledCallbacks.push(() => {
						// 将成功的回调添加到数组中
						setTimeout(() => {
							console.log('2---- then ' + this.status);
							try {
								let x = onFulfilled(this.value);
								resolvePromise(bridgePromise, x, resolve, reject);
							} catch (err) {
								reject(err)
							}
						})
					})
					this.onRejectedCallbacks.push(() => {
						setTimeout(() => {
							try {
								let x = onRejected(this.error);
								resolvePromise(bridgePromise, x, resolve, reject);
							} catch (err) {
								reject(err);
							}
						})
					})
				}
			})
			return bridgePromise;
		}
		// 捕获错误的方法
		catch(onRejected) {
			// 也是调用then方法,给成功的回调传一个null,给失败的回调传入callback
			return this.then(null, onRejected)
		}
	}

	let p1 = new PromiseA((resolve, reject) => {
		// console.log('1');
		resolve(1)

	})

	p1.then((data) => {
		console.log(data);
	})



</script>