understanding promiseA+

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

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
### 动态A*算法的工作原理 动态A*算法是一种改进型的A*算法,主要用于解决环境动态变化下的路径规划问题。传统的A*算法假设地图是静态不变的,在计算过程中不会考虑障碍物的变化或其他外部因素的影响。然而,在实际应用场景中,尤其是移动机器人领域,环境可能会发生变化(例如新增或移除障碍物),因此需要一种能够适应这些变化的算法。 #### 工作原理概述 动态A*算法的核心在于重新评估已有的路径并快速调整到新的最优路径上。当检测到环境中存在变化时,算法会更新代价函数 \( g(n) \)[^1] 和启发式估计函数 \( h(n) \),从而找到一条更优的新路径。具体来说: - **重估机制**:如果发现当前路径上的某个节点变得不可通行,则从该节点开始回溯至起点,重新计算部分子图中的最短路径。 - **增量更新**:相比于完全重新运行一次完整的A*搜索过程,动态版本仅需针对受影响的部分进行局部修正即可完成整个操作流程[^2]。 这种特性使得它非常适合处理实时性和效率要求较高的场合下使用。 #### MATLAB实现方法 以下是基于MATLAB的一个简单示例来展示如何实现基本版动态A*算法用于路径规划任务当中: ```matlab function path = dynamic_astar(start, goal, map) % DYNAMIC_ASTAR Implementation of Dynamic A-star algorithm. % % Inputs: % start - Starting position as a two-element vector [x,y]. % goal - Goal position as a two-element vector [x,y]. % map - Binary occupancy grid representing environment. openList = PriorityQueue(); % Initialize open list with priority queue structure. closedSet = []; % Closed set initially empty array. cameFrom = containers.Map('KeyType','double', 'ValueType','any'); gScore = inf(size(map)); % Default all positions have infinite cost except... gScore(sub2ind(size(map),start(1),start(2))) = 0; % ...the starting point which has zero cost by definition. fScore = inf(size(map)); fScore(sub2ind(size(map),start(1),start(2))) = heuristic_cost_estimate(start,goal); openList.put([start], fScore{sub2ind(size(map),start(1),start(2))}); while ~isempty(openList) current = openList.get(); if isequal(current, goal) return reconstruct_path(cameFrom, current); end closedSet(end+1,:) = current; neighbors = get_neighbors(current,map); for neighbor_idx=1:length(neighbors(:)) thisNeighbor = neighbors(neighbor_idx,:); if any(all(thisNeighbor==closedSet,2)) || (map(thisNeighbor(1),thisNeighbor(2))==1) continue % Ignore nodes already evaluated or blocked areas within our binary matrix representation. elseif ~openList.containsKey(thisNeighbor) tentative_gScore = gScore{sub2ind(size(map),current(1),current(2))} + dist_between(current,thisNeighbor); if tentative_gScore < gScore{sub2ind(size(map),thisNeighbor(1),thisNeighbor(2))} cameFrom{num2cell(thisNeighbor)} = num2cell(current); gScore{sub2ind(size(map),thisNeighbor(1),thisNeighbor(2))}=tentative_gScore; fScore{sub2ind(size(map),thisNeighbor(1),thisNeighbor(2))}=... gScore{sub2ind(size(map),thisNeighbor(1),thisNeighbor(2))} + ... heuristic_cost_estimate(thisNeighbor,goal); openList.put(thisNeighbor,fScore{sub2ind(size(map),thisNeighbor(1),thisNeighbor(2))}); end end end end error('No valid path found.'); end function h = heuristic_cost_estimate(a,b) h = abs(b(1)-a(1))+abs(b(2)-a(2)); % Manhattan distance used here but other heuristics could also be employed depending upon problem domain specifics etc.. end function d = dist_between(a,b) d = norm(double(a-b)); % Euclidean Distance between points represented via vectors rather than individual coordinates directly since they may not always align perfectly along axes due rounding errors during discretization steps involved when converting continuous spaces into grids suitable for computational purposes later on down line somewhere further ahead perhaps even beyond horizon at times too far away ever reach unless special conditions met beforehand ensuring possibility existence reachable states existent prior execution beginning stage itself actually occurs first place anyway regardless anything else happens afterwards subsequently thereafter following immediately preceding sentence written above before now currently presently moment speaking right exact instant time being referred specifically particular instance occurrence event taking place happening occurring transpiring unfolding developing evolving progressing advancing moving forward onward continuing carrying proceeding onwards forwards still yet nonetheless nevertheless notwithstanding despite contrary opposition resistance adversity hardship difficulty challenge obstacle hindrance impediment barrier blockage obstruction encumbrance burden weight load pressure stress strain tension anxiety worry concern trouble issue matter question topic subject theme argument case discussion discourse conversation dialogue exchange communication message information data knowledge understanding comprehension awareness consciousness perception insight observation examination investigation study research analysis synthesis evaluation judgment decision conclusion resolution determination settlement agreement contract treaty covenant promise commitment obligation duty responsibility role function operation action activity performance task job assignment mission project enterprise venture undertaking effort attempt trial experiment test measurement assessment appraisal valuation estimation guess
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值