understanding promiseA+

2 篇文章 0 订阅
本文详细介绍了Promise A+规范,包括术语定义、状态流转、then方法的特性以及微任务的使用。同时,给出了一个简单的Promise实现,讨论了then返回新Promise、状态不可变性以及链式调用的原理。此外,通过实例展示了Promise的使用及状态变化。
摘要由CSDN通过智能技术生成

promiseA+

术语

1、 promise 是一个有then方法的对象或者函数,行为遵循promiseA+规范
2、thenable 是一个有then方法的对象或者函数
3、value 是promise 状态成功的值 resolve的参数 包括各种数据类型 undefined / number / boolean / promise
4、reason 是promise 状态失败的值 reject的参数 表示拒绝的原因
5、exception throw 抛出去的异常

规范

promise的状态 states

promise 有三种状态,注意状态流转关系
resolve、reject是动作 pending、fulfilled、rejected是状态 fulfilled、rejected动作的结果
pending —> resolve(value) —> fulfilled
pending —> reject(reason) —> rejected

pending

1、初始的状态,可改变
2、promise在被resolve 或者 reject之前,都处于pending状态
3、通过resolve —> fulfilled
4、通过 reject —> rejected

fulfilled

1、最终态,不可改变
2、promise经过resolve后变成fulfilled状态
3、必须拥有一个value值 // undefined

rejected

1、最终态,不可改变
2、promise经过reject后变成rejected状态
3、必须拥有一个reason值 // undefined

then

promise 应该提供一个then方法 用来访问最终结果 无论是value还是reason

promise.then(onFulfilled, onRejected)
参数要求

1、onFulfilled、onRejected必须是函数,不是函数应该被忽略
2、onFulfilled 特性

  • promise变成fulfilled时 应该调用onFulfilled 参数是value
  • 变成fulfilled之前不应该被调用
  • 只能调用一次 (用一个变量限制执行次数)

3、onRejected 特性

  • promise变成jejected时 应该调用 onRejected 参数是reason
  • promise变成rejected之前不应该被调用
  • 只能调用一次(用一个变量限制执行次数)

4、onFulfilled 和 onRejected 应该是微任务
注:有使用setTimeout模拟的,但是setTimeout是金典的宏任务 不是微任务 可以使用 queueMicrotask 实现微任务调用
5、then 方法可以被调用多次

  • promise 变成 fulfilled 后, 所有 onFulfilled 的回调都应该按照then的顺序执行。实现promise的时候 需要一个数组来存储 onFulfilled 的 callback
  • promise 变成 rejected 后, 所有 onRejected 的回调都应该按照then的顺序执行。实现promise的时候 需要一个数组来存储 onRejected 的 callback

6、then 的返回值是一个 promise

promise2 = promise1.then(onFulfilled, onRejected)
  • onFulfilled, onRejected 执行的结果为 x, 调用resolvePromise

  • onFulfilled, onRejected 执行时抛出异常, promise2 需要被 reject

  • 如果 onFulfilled 不是一个函数, promise2 以 promise1的 value 触发 fulfilled

  • 如果onRejected 不是一个函数,promise2 以 promise1的 reason 触发 rejected

    问:then 返回的是一个新的 promise 还是旧的 promise (新)

7、resolvePromise

resolvePromise(promise2, x, resolve, reject)
  • 如果promise2 和 x 相等 那么 reject TypeError
  • 如果 x 是一个 promise
    1. 如果 x 是 pending, promise的状态也必须是 pending,直到x变成 fulfilled / rejected
    2. 如果 x 是 fulfilled, fulfill promise with then same value
    3. 如果 x 是 rejected,reject promise with then same reason
  • 如果 x 是一个 Object 或者 function
    1. let then = x.then
    2. 如果 x.then 这一步出错, try catch(e), reject(e)
    3. 如果 then 是一个函数, then.call(x, resolvePromiseFn, rejectPromiseFn)
    4. resolvePromiseFn 的入参是 y, 执行 resolvePromise(promise2, y, resolve, reject)
    5. 如果调用then抛出了异常, resolvePromiseFn, rejectPromiseFn执行完了就不管了,如果没有被调用 直接 reject reason
手写promise
const PENDING = 'pending'
const FULFILLEF = 'fulfilled'
const REJECTED = 'rejected'
class MPromise {
	FULFILLED_CALLBACK_LIST = []
	REJECTED_CALLBACK_LIST = []
	_status = PENDING
	/**
	 * @param {Function} fn (resolve, reject)
	 */
	constructor (fn) {
		// 初始状态为pending
		this.status = PENDING 
		this.value = null
		this.reason = null
		
		try {
			fn(this.resolve.bind(this), this.reject,bind(this))   // 用bind 防止传进来的函数不是箭头函数
		} catch (e) {
			this.reject(e)
		}
	}

	get status () {
		return this._status 
	}
	
	set ststus (newStatus) {
		this._status  = newStatus
		switch (newStatus) {
			case FULFILLED:
				this.FULFILLED_CALLBACK_LIST.forEach(callback => {
					callback(this.value)
				})
				break
			case REJECTED:
				this.REJECTED_CALLBACK_LIST.forEach(callback => {
					callback(this.reason)
				})
				break
		}
	}

	resolve (value) {
		// 判断状态 只有pending状态才能变成fulfilled
		if (this.status === PENDING ) {
			this.value = value
			this.status = FULFILLEF 
		}
	}

	reject (reason) {
		// 判断状态 只有pending状态才能变成 rejected
		if (this.status === PENDING ) {
			this.reason = reason
			this.status = REJECTED
		}
	}

	then (onFulfilled, onRejected) {
		//6.3、如果 onFulfilled 不是一个函数, promise2 以 promise1 的 value 触发 fulfilled
		const realOnFulfilled = this.isFunctin(onFulfilled) ? onFulfilled : (value) => { return value }
		//6.4 、如果onRejected 不是一个函数,promise2 以 promise1 的 reason 触发 rejected
		const realOnRejected = this.isFunctin(onRejected) ? onRejected : (reason) => { throw reason }
		
		// then 的返回值整体是一个promise
		const promise2 = new MPromise((resolve, reject) => {
			// 6.2、onFulfilled, onRejected 执行时抛出异常, promise2 需要被 reject
			const fulfilledMicrotask = () => {
				// 6.1、onFulfilled, onRejected 执行的结果为 x, 调用 resolvePromise
				queueMicrotask(() => { // 微任务
					try {
						let x = realOnFulfilled(this.value)
						this.resolvePromise(promise2, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
			}
			const rejectefMicrotask = () => {
				// 6.1、onFulfilled, onRejected 执行的结果为 x, 调用 resolvePromise
				queueMicrotask(() => { // 微任务
					try { 
						let x = realOnRejected(this.value)
						this.resolvePromise(promise2, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
			}
			
			//当调用then的时候 不同状态 调用不同函数
			switch (this.status) {
				case PENDING:
					this.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask)
					this.REJECTED_CALLBACK_LIST.push(rejectefMicrotask)
					break
				case FULFILLED:
					fulfilledMicrotask()
					break
				case REJECTER:
					rejectefMicrotask()
					break
			}
		})
		return promise2
	}

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

	resolvePromise (promise2, x, resolve, reject) {
		// 7.1、如果promise2 和 x 相等 那么 reject TypeError
		if (promise2 === x) {
			return reject(new TypeError('The promise and then return value are then same'))
		}
		
		if (x instanceof MPromise) {
			// 如果 x 是一个 promise 让新的promise接收x状态 即继续执行 x , 如果执行的时候拿到一个y, 那么继续解析y
			queueMicrotask(() => { // 微任务
				x.then(y => {
					this.resolvePromise(promise2, y, resolve, reject)
				}, reject)
			})
		} else if (typeof x === 'object' || this.isFunctin(x)) {
			if (x === null) {
				return resolve(x)
			}

			let then = null
			
			try { // 取x.then 赋值给then
				then = x.then
			} catch (e) {
				return reject(e)
			}
			// 如果获取到的then是一个函数
			if (this.isFunctin(then)) {
				let called = false
				try {
					then.call(
						x,
						(y) => {
							if (called) {
								return
							}
							called = true
							this.resolvePromise(promise2, y, resolve, reject)
						}, // onFulfilled
						(r) => {
							if (called) {
								return
							}
							called = true
							reject(r)
						} // onRejected
					)
				} catch (e) {
					if (called) {
						return
					}
					reject(e)
				}
			} else {
				resolve(x)
			}
		} else {
			resolve(x)
		}
	}

	isFunctin (value) {
		return typeof value === 'function'
	}

	static resolve (value) { // 静态方法 不用new就可以调用  使用:MPromise.resolve()
		if (value instanceof MPromise) { // value 是个promise 直接返回
			return value
		}

		return new MPromise((resolve) => { // value 不是promise 包装成一个 promise 返回
			resolve(value)
		})
	}

	static reject (reason) { // 静态方法
		return new MPromise((resolve, reject) => {
			reject(reason)
		})
	}

	static race (promiseList) {
		return new MPromise((resolve, reject) => {
			if (promiseList.length === 0) {
				return resolve()
			} else {
				for (let i = 0; i < promiseList.length; i++) {
					MPromise.resolve(promiseList[i]).then(
						(value) => { return resolve(value) },
						(reason) => { return reject(reason) }
					)
				}
			}
		})
	}
}
测试
const test = new MPromise((resolve, reject) => {
	setTimeOut(() => {
		resolve(111)
	}, 1000)
}).then((value) => {
	console.log('then')
})

setTimeout(() => {
	// 问:value 是什么   答:undefined   状态是fulfilled   原因: then调用没有return(无返回值),默认 return undefined
	console.log(test)
}, 3000)

问:链式调用每次调用返回一个新的promise 为什么 then() 中 pending状态时候 要使用数组来存? 答:promise 可以多次同一实例调用
调用方式一:

new MPromise((resolve, reject) => {}).then(() => {}).then(() => {}).then(() => {})

调用方式二:

const test = new MPromise((resolve, reject) => {})
test.then(() => {})
test.then(() => {})
test.then(() => {})
const test = new MPromise((resolve, reject) => {
	setTimeOut(() => {
		resolve(111)
	}, 1000)
}).catch((reason) => {
	console.log('报错' + reason)
	// 问 test status 的状态是什么  答:pending 
	// 原因:打印promise的时候,整个回调并没执行完成  只有当整个回调完成后才能更改状态
	console.log(test)
})

setTimeOut(() => {
   // 问 test status 的状态是什么  答:fulfilled 
   // 原因: catch 函数会返回一个新的promise, 成功执行完成,新的promise 的状态会变成fulfilled
	console.log(test)
}, 3000)

// 1、catch 函数会返回一个新的promise, 而且test就是这个新的promise
// 2、catch 回调里 打印promise的时候,整个回调并没执行完成  只有当整个回调完成后才能更改状态
// 3、catch 回调函数,如果成功执行完成,那么新的promise 的状态会变成fulfilled
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值