笔记 - PromiseA+规范

背景

在Promise出来之前,前端的所有异步操作都是基于回调函数,当回调层级嵌套过多,会造成了代码中产生大量的回调地狱,非常不易于可读性和可维护性。
例如:

	fetchA('xxx', function() {
		fetchB('xxx', function() {
			fetchC('xxx', function() {
				// 业务代码
			})
		})
	})

相同的逻辑使用Promise:

	fetchA('xxx')
		.then(function() {
			return fetchB('xxx');
		})
		.then(function() {
			return fetchC('xxx');
		})
		.then(function() {
			// 业务代码
		})

手动实现一个Promise

思路梳理

1、选用ES6的class实现,主要是需要使用class中的getter、setter属性。
2、基于PromiseA+规范 PromiseA+规范文档

代码实践

创建MPromise类,并初始化

	// 三种状态
	const PENDING = 'pending';
	const FULFILLED = 'fulfilled';
	const REJECTED = 'rejected';

	class MPromise {
		constructor() {
			this.status = PENDING;
			this.value = null;
			this.reason = null;
		}
	}

实现resolve, reject 方法

	class MPromise {
		constructor() {
			// ....
		}

		resolve(value) {
			if (this.status === PENDING) {
				this.value = value;
            	this.status = FULFILLED;
			}
		}

		reject(reason) {
			if (this.status === PENDING) {
				this.reason = reason;
            	this.status = REJECTED;
			}
		}
	}

继续完善构造函数中的逻辑

	class MPromise {
		constructor(fn) { // 将传入的函数立即执行,并注入resolve,reject
			this.status = PENDING;
			this.value = null;
			this.reason = null;

			try{
				fn(this.resolve.bind(this), this.reject.bind(this));
			}catch(e) {
				this.reject(e);
			}
		}
	}

实现then方法 (ps: 返回一个新的promise)

	class MPromise{
		constructor(fn){...}
		resolve(value){...}
		reject(reason){...}
		
		then(onFulfilled, onRejected) {
			//如果onFulfilled, onRejected不是函数,则必须忽略它
			const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => {
				return value
			}
			const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => {
				return reason;
			}

			const promise2 = new MPromise((resolve, reject) => {
				switch(this.status) {
					case FULFILLED: {
						realOnFulfilled(this.value);
						break;
					}
					case REJECTED: {
						realOnRejected(this.reason);
						break;
					}
					case PENDING: {
						// 如果是异步操作怎么处理?
					}
				}
			});
	
			return promise2;
		}

		isFunction(fn) {
			return typeof fn === 'function';
		}
	}

添加then方法的异步处理

	class MPrmose {
		// 添加缓存队列
		FULFILLED_CALLBACK_LIST = [];
		REJECTED_CALLBACK_LIST = [];
		// 使用class的 setter getter 来监听变化
		// 解决异步调用的问题
		_status = PENDING;

		constructor(fn){...}
		resolve(value){...}
		reject(reason){...}

		get status() {
			return this._status;
		}

		set status(newStatus) {
			this._status = newStatus;
			
			switch(newStatus) {
				case FULFILLED: {
					this.FULFILLED_CALLBACK_LIST.forEach(callback => {
						callback(this.value);
					})
				}
				case REJECTED: {
					this.REJECTED_CALLBACK_LIST.forEach(callback => {
						callback(this.reason)
					})
				}
			}
		}
	
		then(onFulfilled, onRejected) {
			//如果onFulfilled, onRejected不是函数,则必须忽略它
			const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => {
				return value
			}
			const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => {
				return reason;
			}

			const promise2 = new MPromise((resolve, reject) => {
				// 如果其中一个onFulfilled或onRejected抛出异常e
				// 则promise2必须reject(e)。
				const fulfilledMicrotask = () => {
					try {
						const x = realOnFulfilled(this.value);
						this.reslovePromise(x, promise2, resolve, reject);
					} catch (e) {
						this.reject(e);
					}
				}

				const rejectedMicrotask = () => {
					try {
						const x = realOnRejected(this.reason);
						this.reslovePromise(x, promise2, resolve, reject);
					} catch (e) {
						this.reject(e);
					}
				}

				switch(this.status) {
					case FULFILLED: {
						fulfilledMicrotask(this.value);
						break;
					}
					case REJECTED: {
						rejectedMicrotask(this.reason);
						break;
					}
					case PENDING: {
						FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask);
						REJECTED_CALLBACK_LIST.push(rejectedMicrotask);
						break;
					}
				}
			});
	
			return promise2;
		}

		isFunction(fn) {
			return typeof fn === 'function';
		}
	}

实现reslovePromise

	class MPromise{
		// ...

		resolvePromise(x, promise2, resolve, reject){
			// 如果 newPromise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 newPromise
	        // 这是为了防止死循环
	        if (promise2 === x) {
	            return reject(new TypeError('The promise and the return value are the same'));
	        }
	
	        if (x instanceof MPromise) {
	            // 如果 x 为 Promise ,则使 newPromise 接受 x 的状态
	            // 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y
	            queueMicrotask(() => {
	                x.then((y) => {
	                    this.resolvePromise(promise2, y, resolve, reject);
	                }, reject);
	            })
	        } else if (typeof x === 'object' || this.isFunction(x)) {
	            // 如果 x 为对象或者函数
	            if (x === null) {
	                // null也会被判断为对象
	                return resolve(x);
	            }
	
	            let then = null;
	
	            try {
	                // 把 x.then 赋值给 then 
	                // 这种首先保存 x.then 的引用,然后测试此引用,再调用此引用的处理,避免了对 x.then 属性的多次访问。这种预防措施在面对一些特殊访问器时十分重要,因为有的访问器每次访问都会导致其值的改变。
	                then = x.then;
	            } catch (error) {
	                // 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
	                return reject(error);
	            }
	
	            // 如果 then 是函数
	            if (this.isFunction(then)) {
	                let called = false;
	                // 将 x 作为函数的作用域 this 调用
	                // 传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise
	                try {
	                    then.call(
	                        x,
	                        // 如果 resolvePromise 以值 y 为参数被调用,则运行 resolvePromise
	                        (y) => {
	                            // 需要有一个变量called来保证只调用一次.
	                            if (called) return;
	                            called = true;
	                            this.resolvePromise(promise2, y, resolve, reject);
	                        },
	                        // 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
	                        (r) => {
	                            if (called) return;
	                            called = true;
	                            reject(r);
	                        });
	                } catch (error) {
	                    // 如果调用 then 方法抛出了异常 e:
	                    if (called) return;
	
	                    // 否则以 e 为据因拒绝 promise
	                    reject(error);
	                }
	            } else {
	                // 如果 then 不是函数,以 x 为参数执行 promise
	                resolve(x);
	            }
	        } else {
	            // 如果 x 不为对象或者函数,以 x 为参数执行 promise
	            resolve(x);
	        }
		}
	}

静态 resolve,reject 实现

	class MPromise {
		// ...
		static resolve(value) {
			return new MPromise(resolve => {
				resolve(value);
			})
		}

		static reject(reason) {
			return new MPromise((resolve, reject) => {
				reject(reason);
			})
		}
	}

catch 实现

	class MPromise {
		// ...

		catch(onRejected) {
			return this.then(null, onRejected);
		}
	}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值