ES6中Promise的手动实现

我的这个实现也是参照了网上一些牛人的实现基础上,加了一些自己的想法,也算是踩在巨人的肩膀上吧。由于也是初学ES6,如有实现不妥的地方,希望大家给予批评指正。

const MyPromise = (function() {
	const PENDING = "PENDING";
	const FULFULLED = "FULFULLED";
	const REJECTED = "REJECTED";
	
	// 通过Symbol实现不可以被外部访问的私有属性
	const status = Symbol("status");						// 状态
	const value = Symbol("value");							// MyPromise的当前值
	const onFulfilledFuncs = Symbol("onFulfilledFuncs");	// resolve时调用的函数队列
	const onRejectedFuncs = Symbol("onRejectedFuncs");		// reject时调用的函数队列
	const resolveFunc = Symbol("resolveFunc");				// 内部resolve函数
	const rejectFunc = Symbol("rejectFunc");				// 内部reject函数
	
	return class {
		constructor(executor) {
			if (typeof executor !== "function") {
				throw new TypeError(`MyPromise resolver ${executor} is not a function`);
			}
			this[status] = PENDING;
			this[value] = undefined;
			this[onFulfilledFuncs] = [];
			this[onRejectedFuncs] = [];
			
			try {
				// 执行传入构造器的执行函数,传入内部resolve和reject函数
				executor(this[resolveFunc].bind(this), this[rejectFunc].bind(this));
			} catch(e) {
				this[rejectFunc](e);
			}
		}
		
		[resolveFunc](val) {
			if (this[status] !== PENDING) return;
			if (val instanceof MyPromise) {
				val.then(this[resolveFunc].bind(this), this[rejectFunc].bind(this));
			} else {
				this[value] = val;
				this[status] = FULFULLED;
				let func;
				while (func = this[onFulfilledFuncs].shift()) {
					func(val);
				}
			}
		}
		
		[rejectFunc](reason) {
			if (this[status] !== PENDING) return;
			this[value] = reason;
			this[status] = REJECTED;
			let func;
			while (func = this[onRejectedFuncs].shift()) {
				func(reason);
			}
		}
		
		// 通过[Symbol.species]解决继承问题
		// MyPromise的任何实例方法和静态方法返回MyPromise类型对象时,均返回派生类的实例对象
		// 例:
		// class YourPromise extends MyPromise {}
		// let promise = new MyPromise((resolve, reject) => {});
		// console.log(YourPromise.resolve(promise) instanceof YourPromise);	// true
		static get [Symbol.species]() {
			return this;
		}
		
		then(onFulfilled, onRejected) {
			return new this.constructor[Symbol.species]((resolve, reject) => {
				
				const onFulfilledFunc = () => {
					// 通过MutationObserver实现微任务,构造函数的参数即节点发生变化时的回调函数
					const observer = new MutationObserver(() => {
						try {
							if (typeof onFulfilled !== "function") return resolve(this[value]);
							let result = onFulfilled(this[value]);
							// 如果返回值类型继续为MyPromise,则将此MyPromise对象的回调委托给当前MyPromise对象
							if (result instanceof MyPromise) {
								result.then(resolve, reject);
							} else {
								resolve(result);
							}
						} catch(e) {
							reject(e);
						}
					});
					// 为了节约开销,创建一个文本节点
					const textNode = document.createTextNode("");
					observer.observe(textNode, {
						characterData: true		// 监视文本数据
					});
					textNode.data = 1;		// 文本节点数据发生变化,触发observer绑定的回调函数
				};
				
				const onRejectedFunc = () => {
					const observer = new MutationObserver(() => {
						try {
							if (typeof onRejected !== "function") throw this[value];
							let result = onRejected(this[value]);
							if (result instanceof MyPromise) {
								result.then(resolve, reject);
							} else {
								resolve(result);
							}
						} catch(e) {
							reject(e);
						}
					});
					const textNode = document.createTextNode("");
					observer.observe(textNode, {
						characterData: true
					});
					textNode.data = 1;
				};
				
				switch (this[status]) {
					case PENDING : 
						this[onFulfilledFuncs].push(onFulfilledFunc);
						this[onRejectedFuncs].push(onRejectedFunc);
						break;
					case FULFULLED :
						onFulfilledFunc();
						break;
					case REJECTED :
						onRejectedFunc();
				}
			});
		}
		
		catch(onRejected) {
			return this.then(null, onRejected);
		}
		
		finally(cb) {
			return this.then(value => MyPromise.resolve(cb()).then(() => value),
							 error => MyPromise.resolve(cb()).then(() => { throw error; }));
		}
		
		static resolve(p) {
			if (p instanceof MyPromise) {
				Object.setPrototypeOf(p, this[Symbol.species].prototype);
				return p;
			}
			return new this[Symbol.species]((resolve, reject) => {
				// thenable对象
				if (p && p.then && typeof p.then === "function") {
					p.then(resolve, reject);
				} else {
					resolve(p);
				}
			});
		}
		
		static reject(p) {
			return new this[Symbol.species]((resolve, reject) => {
				reject(p);
			});
		}
		
		// promises不一定是promise数组,但其必须实现Iterator接口[Symbol.iterator]
		// 通过MyPromise.resolve()确保将每一个元素转化为MyPromise对象
		// 如果传入的是空数组,依然将其设置为当前MyPromise的值
		static all(promises) {
			return new this[Symbol.species]((resolve, reject) => {
				if (promises.length === 0) return resolve([]);
				let results = [];
				let count = 0;
				// 返回的结果数组里元素的位置与传入的promises里元素的位置一一对应
				promises.forEach((p, index) => {
					MyPromise.resolve(p).then(value => {
						results[index] = value;
						if (++count === promises.length) {
							resolve(results);
						}
					}, reason => reject(reason));
				});
				// 注意:传入的参数为非空数组时,不能将判断移到forEach外,会存在异步问题
				//if (count === promises.length) {
				//	resolve(results);
				//}
			});
		}
		
		static race(promises) {
			return new this[Symbol.species]((resolve, reject) => {
				for (let p of promises) {
					MyPromise.resolve(p).then(value => resolve(value), reason => reject(reason));
				}
			});
		}
	};
}());

注意:then(onFulfilled, onRejected) 也可以用 then(onFulfilled).catch(onRejected) 的方式实现,但是这两种方式有一个区别。then(onFulfilled, onRejected) 注册了一个微任务,而 then(onFulfilled).catch(onRejected) 则注册了两个微任务,因为 catch 方法本质上又调用了一次 then 方法。

参考链接:
1、Promise实现原理(附源码)
2、通过MutationObserver实现Promise

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值