封装Promise

202 阅读3分钟
class Promise {

	constructor(executor) {
		// 为实例对象添加属性
		this.PromiseState = 'pending'
		this.PromiseResult = null
		// 添加此属性为保存then方法中状态为pending时的回调
		this.callbacks = []

		// 保存实例对象this的值
		const self = this

		function resolve(data) {
			// console.log(this); // Window
			// console.log(self) // Object

			// 判断Promise状态只能修改一次
			if (self.PromiseState !== 'pending') return

			// 修改对象状态(promiseState)
			self.PromiseState = 'fulfilled'
			// 设置对象结果值(promiseResult)
			self.PromiseResult = data

			// 如果是异步回调会在这里执行
			setTimeout(() => {
				self.callbacks.forEach(item => item.onResolved(data))
			});
		}

		function reject(data) {
			if (self.PromiseState !== 'pending') return

			self.PromiseState = 'rejected'
			self.PromiseResult = data

			// 如果是异步回调会在这里执行
			setTimeout(() => {
				self.callbacks.forEach(item => item.onRejected(data))
			});

		}

		// throw => try-catch
		try {
			// 同步调用执行器函数
			executor(resolve, reject)
		} catch (error) {
			reject(error)
		}
	}

	// then()
	then(onResolved, onRejected) {
		const self = this

		// 给then()提供了两个参数,第二个失败的参数可以不传,可以直接调用catch()方法,所以在这里对第二个参数进行处理,如果不传,那么在这里抛出错误,当调用catch()的时候,就会接收到抛出的错误
		if (typeof onRejected !== 'function') {
			onRejected = reason => { throw reason }
		}

		// 第一次then()可以不传参数,那么给onResolved也设置一个默认值,如果不传,那么默认传递一个函数,返回结果
		if (typeof onResolved !== 'function') {
			onResolved = value => value
		}

		// then()返回结果如果是一个Promise对象
		return new Promise((resolve, reject) => {

			// 封装函数callback => try-catch
			function callback(type) {
				try {
					// 这个就是Promise.then()的执行结果
					let result = type(self.PromiseResult)
					if (result instanceof Promise) {
						result.then(v => {
							resolve(v)
						}, r => {
							reject(r)
						})
					} else {
						// 结果对象的状态为成功,调用成功的函数
						resolve(result)
					}
				} catch (e) {
					reject(e)
				}
			}

			// 调用回调函数
			if (this.PromiseState === 'fulfilled') {
				setTimeout(() => {
					callback(onResolved)
				});
			}

			if (this.PromiseState === 'rejected') {
				setTimeout(() => {
					callback(onRejected)
				});
			}

			// 如果是pending状态那么就保存回调函数,在Promise函数中得到状态之后再执行对应的回调
			if (this.PromiseState === 'pending') {
				this.callbacks.push({
					onResolved() {
						callback(onResolved)
					},
					onRejected() {
						callback(onRejected)
					}
				})
			}
		})
	}

	// catch()
	catch(onRejected) {
		return this.then(null, onRejected)
	}

	// resolve()
	static resolve(value) {
		return new Promise((resolve, reject) => {
			if (value instanceof Promise) {
				value.then(v => {
					resolve(v)
				}, r => {
					reject(r)
				})
			} else {
				resolve(value)
			}
		})
	}

	// reject()
	static reject(reason) {
		return new Promise((resolve, reject) => {
			reject(reason)
		})
	}

	// all()
	static all(promises) {
		return new Promise((resolve, reject) => {
			let count = 0
			let result = []
			for (let i = 0; i < promises.length; i++) {
				promises[i].then(v => {
					result[i] = v
					count++
					if (count === promises.length) {
						resolve(result)
					}
				}, r => {
					reject(r)
				})
			}
		})
	}

	// race()
	static race(promises) {
		return new Promise((resolve, reject) => {
			for (let i = 0; i < promises.length; i++) {
				promises[i].then(v => {
					resolve(v)
				}, r => {
					reject(r)
				})
			}
		})
	}
}

/*描述*
 * 改变Promise对象的状态有三种方式
 * 	=> resolve
 * 	=> reject
 * 	=> throw
 * 
 * Promise对象的状态只能修改一次
 * 
 * Promise.then()接收两个参数,成功的回调和失败的回调,回调接收成功或者失败的结果
 * 
 * 异步任务执行回调函数then()
 * 
 * 指定多个回调then()
 * 
 * then()返回结果
 * 	=> 如果回调函数的返回值为一个非Promise对象,那么返回结果为fulfilled
 * 	=> 如果回调函数的返回值为一个Promise对象,那么返回结果由Promise对象的返回结果来决定
 * 
 * 异步任务返回then()结果
 * 
 * 封装 try catch 方法
 * 
 * catch()指定失败的回调函数,这个方法可以异常穿透,可以捕获中间错误,可以进行值传递,then()第一个方法也可以不传
 * 
 * resolve()返回一个Promise对象
 * 
 * reject()返回一个Promise对象,状态永远为失败的状态
 * 
 * all()返回Promise对象,状态如果都成功,那么才是成功,返回所有成功的结果,如果有一个失败,那么状态就是失败,返回那个失败的结果
 * 
 * race()返回一个Promise对象,状态由最先改变状态的那个Promise对象决定,结果值也是
 * 
 * then()回调函数是异步执行的
 * */