手写符合Promise/A+规范的Promise

const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";

function MyPromise(fn){
	const that = this;
	that.state = PENDING;
	that.value = null;
	that.resolvedCallbacks = [];
	that.rejectedCallbacks = [];
	function resolve(value){
		// 判断传入的值是否为 Promise 类型
		if( value instanceof MyPromise){
			return value.then(resolve, reject)
		}
		// 为了保证函数的执行顺序,需要将两个函数体代码使用 setTimeout 包裹起来
		setTimeout(()=>{
			// 只有等待状态才可以改变状态
			if(that.state == PENDING){
				// 将当前状态更改为对应状态,并且将传入的值赋值给 value
				that.state = RESOLVED;
				that.value = value;
				// 遍历回调数组并执行
				that.resolvedCallbacks.map(cb => cb(that.value));
			}
		},0)
		
	}
	function reject(value){
		setTimeout(()=>{
			if(that.state == PENDING){
				that.state == REJECTED;
				that.value = value;
				that.rejectedCallbacks.map( cb => cb(that.value));
			}
		})
	}
	try {
		fn(resolve, reject)
	} catch (e) {
		reject(e)
	}

}
MyPromise.prototype.then = function(onFulfilled, onRejected){
	const that = this;
	// 判断两个参数是否为函数类型, 这两个参数是可选参数
	// 当参数不是函数类型时,需要创建一个函数赋值给对应的参数,同时也实现了透传
	onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
	onRejected = typeof onRejected === 'function' ? onRejected : r => {throw r};
	if(that.state === PENDING){
		// 返回了一个新的 Promise 对象,并在 Promise 中传入了一个函数
		// 规范规定,执行 onFulfilled 或者 onRejected 函数时会返回一个 x,并且执行 Promise 解决过程,这是为了不同的 Promise 都可以兼容使用,比如 JQuery 的 Promise 能兼容 ES6 的 Promise
		return (promise2 = new MyPromise((resolve, reject)=>{
			that.resolvedCallbacks.push(()=>{
				try {
					const x = onFulfilled(that.value)
					resolutionProcedure(promise2, x, resolve, reject)
				}catch (r) {
					reject(r)
				}
			});
			that.rejectedCallbacks.push(()=>{
				try {
					const x = onRejected(that.value)
					resolutionProcedure(promise2, x, resolve, reject)
				} catch (r) {
					reject(r)
				}
			});
		}))
	}
	if(that.state === RESOLVED){
		return (promise2 = new MyPromise((resolve, reject)=>{
			setTimeout(()=>{
				try {
					const x = onFulfilled(that.value)
					resolutionProcedure(promise2, x, resolve, reject)
				} catch (reason) {
					reject(r)
				}
			})
		}))
	}
	if(that.state === REJECTED){
		return (promise2 = new MyPromise((resolve, reject)=>{
			try {
				const x = onRejected(that.value);
				resolutionProcedure(promise2, x, resolve, reject)
			}catch(r){
				reject(r)
			}
		}))
	}

	function resolutionProcedure(promise2, x, resolve, reject) {
		if (promise2 === x) {
			return reject(new TypeError('Error'))
		}
		if (x instanceof MyPromise) {
			x.then(function(value) {
					resolutionProcedure(promise2, value, resolve, reject)
			}, reject)
		}
		// 创建一个变量 用于判断是否已经调用过函数
	// 	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)
	// 	}
	}
}
// 创建一个实例 
new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 0)
}).then(value => {
  console.log(value)
})

  

posted @ 2019-07-09 20:10  进阶之路-前端  阅读(327)  评论(0编辑  收藏  举报