手撕promise

56 阅读4分钟
const statu = {
	Pending: 'PENDING',
	Fulfilled: 'FULFILLED',
	Rejected: 'REJECTRD'
}

// 需要兼容其他人的promise
const resolvePromise = (x, promise2, resolve, reject) => {
	//resolvePromise 主要作用呢 根据x的值来解析promise2是成功还是失败
	// 如果promise和x指向同一对象,promise则以拒绝TypeError为理由。
	if (x === promise2) {
		reject(new TypeError(`TypeError: Chaining cycle detected for promise #<Promise>`))
	}

	//判断x的值 是普通值得话调用成功函数 是promise对象那么就采用他的状态
	//如何判断一个值是否是promise(看x有没有then方法,有then方法说明就是promise)
	if ((typeof x === 'object' && x !== null) || typeof x === 'function') {

		// 这是x有可能是一个对象或函数
		// 在继续进行判断

		//如果检索属性x.then中抛出的异常的结果e,拒绝promise与e作为的原因。
		// If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.

		// called的原因如果同时调用resolvePromise和rejectPromise,或者对同一参数进行了多次调用,则第一个调用优先,而所有其他调用均被忽略。
		//  这里解析的x 如果是一个promise的话 可能是别人家的promise
		//如果同时调用resolvePromise和rejectPromise,或者对同一参数进行了多次调用,则第一个调用优先,而所有其他调用均被忽略。
		let called
		try {
			let then = x.then //取出then方法
			// 如果then是函数,请使用x as this,第一个参数resolvePromise和第二个参数进行调用rejectPromise,
			// If thenis a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise
			if (typeof then == 'function') {
				//有then方法就是promise
				// call的目的是 防止再去取一回then 因为then方法中没有this所以需要call一下// 就是promise, 复用上次取出来的then方法  x.then
				then.call(x, y => {
					if (called) return
					called = true
					//这里y有可能也是一个promise  需要递归解析y的值,直到这个结果是一个普通的值为止,将结果作为promise2的成功或失败
					resolvePromise(y, promise2, resolve, reject)
				}, r => {
					//一旦失败直接失败即可
					if (called) return
					called = true
					reject(r)
				})
			} else {
				//没有then的话就是一个普通的对象直接成功回调节课
				resolve(x)
			}
		} catch (e) {
			//TODO handle the exception
			if (called) return
			called = true
			reject(e)
		}

	} else {
		//普通值 直接执行成功函数
		resolve(x)
	}
}


class Promise {
	//promise中executor是自执行器
	constructor(executor) {
		this.status = statu.Pending
		this.value = undefined
		this.reason = undefined
		this.onResolvedCallbacks = []
		this.onRejectedCallbacks = []
		// pending=>fulfilled  状态从进行中=>已完成
		const resolve = (value) => {
			// 如果value 是一个promise,那我们的库中应该也要实现一个递归解析
			if (value instanceof Promise) {
				return value.then(resolve, reject)
			}
			if (this.status == statu.Pending) {
				this.status = statu.Fulfilled
				this.value = value
				this.onResolvedCallbacks.forEach(fn => fn())
			}
		}

		// pending=>rejected  状态从进行中=>失败
		const reject = (reason) => {
			if (this.status == statu.Pending) {
				this.status = statu.Rejected
				this.reason = reason
				this.onRejectedCallbacks.forEach(fn => fn())
			}
		}
		// try catch 实例后执行时  捕获错误 遇到立即执行
		try {
			executor(resolve, reject) //立即执行器
		} catch (e) {
			//TODO handle the exception
			reject(e)
		}
	}
	//Promise.prototype 上的 then和 catch 方法总会返回一个全新的 Promise 对象。
	then(onFulfilled, onRejected) {
		// 这两个onFulfilled和onRejected可选的参数:
		// 如果onFulfilled不是函数,则必须将其忽略。
		// 如果onRejected不是函数,则必须将其忽略。
		onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : v => v;
		onRejected = typeof onRejected === 'function' ? onRejected : err => {
			throw err
		};
		let promise2 = new Promise((resolve, reject) => {
			//状态转化为成功是执行成功的回调
			if (this.status == statu.Fulfilled) {
				setTimeout(() => {
					try {
						let x = onFulfilled(this.value)
						resolvePromise(x, promise2, resolve, reject)
					} catch (e) {
						//TODO handle the exception
						reject(e);
					}
				}, 0)
			}
			//状态转回为失败 执行失败的回调
			if (this.status == statu.Rejected) {

				setTimeout(() => {
					try {
						let x = onRejected(this.reason)
						resolvePromise(x, promise2, resolve, reject)
					} catch (e) {
						//TODO handle the exception
						reject(e);
					}
				}, 0)
			}
			//异步
			if (this.status == statu.Pending) {
				//当执行异步时  用户还没有调用resolve或reject方法时 先驯如缓存缓存病例
				this.onResolvedCallbacks.push(() => {
					setTimeout(() => {
						try {
							let x = onFulfilled(this.value)
							resolvePromise(x, promise2, resolve, reject)
						} catch (e) {
							//TODO handle the exception
							reject(e);
						}
					}, 0)
				})
				this.onRejectedCallbacks.push(() => {
					setTimeout(() => {
						try {
							let x = onRejected(this.reason)
							resolvePromise(x, promise2, resolve, reject)
						} catch (e) {
							//TODO handle the exception
							reject(e);
						}
					}, 0)
				})
			}
		})
		return promise2
	}
	catch (errCallback) {
		return this.then(null, errCallback)
	}
	static resolve(val) {
		return new Promise((resolve, reject) => {
			resolve(val);
		})
	}
	static reject(reason) {
		return new Promise((resolve, reject) => {
			reject(reason);
		})
	}
	//返回一个promise
	//若promise传入的数组状态都成功,则按序返回一个执行后的新的数组
	//若遇到失败 则返回第一个结果的失败原因,遇到失败返回失败后续不再执行
	static all(values) {
		return new Promise((resolve, reject) => {
			let resultArr = [];
			let orderIndex = 0;

			const processResultByKey = (value, index) => {
				resultArr[index] = value
				if (++orderIndex === values.length) {
					resolve(resultArr)
				}
			}
			for (let i = 0; i < values.lengthl; i++) {
				let value = values[i]
				if (value && value.then === 'function') {
					value.then((value) => {
						//将数组中的按执行顺序返回结果
						processResultByKey(value, i)
					}, reject)
				} else {
					processResultByKey(value, i)
				}
			}
		})
	}
	//Promise.race函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。
	// 它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。
	//不管是成功还是失败 谁先执行则返回谁(赛跑)
	static race(values){
		return new Promise((resolve,reject)=>{
			if(values.length==0){
				return
			}
			for(let i=0;i<values.length;i++){
				Promise.resolve(values[i].then(data=>{
					resolve(data)
					return
				},err=>{
					reject(err)
					return
				})
			}
		})
	}
}

// promises-aplus-tests promise.js
//npm install -g promises-aplus-tests
//测试promise是否符合规范
Promise.defer = Promise.deferred = function() {
	let dfd = {};
	dfd.promise = new Promise((resolve, reject) => {
		dfd.resolve = resolve;
		dfd.reject = reject;
	});
	return dfd;
}

//finally

promise.prototype.finally=function(callback){
	return this.then((value)=>{
		return Promise.resolve(callback()).then(() => value)
	},(reason)=>{
		return Promise.resolve(callback()).then(() => { throw err })
	})
}


module.exports = Promise


// promise的使用

//只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;有一个成功就返回成功
// 如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。所有失败返回一个数组结果
// promise.any()


// Promise.allSettled()
//不管成功还是失败 所有都执行
// [
//    { status: 'fulfilled', value: 42 },
//    { status: 'rejected', reason: -1 }
// ]