Promise难点

Promise解释原名叫做’承诺’,表达的意思是将来会执行的操作,代表异步操作;
特点:
它总共分为两个阶段和三个状态;
首先两个阶段是 unsettled未决阶段和 settled已决阶段;
然后三个状态 penging 等待和resolved 已处理以及reject 已拒绝
基本用法:
创建一个简单的Promise
代码演示:

 <script type="text/javascript">
	  	 const pro = new Promise((resolve , reject) => {
	  	 	if(true){
                 resolve(data)
	  	 	}else{
                 reject(err)
	  	 	}
	  	 })
	  </script>

由上面的代码可知这个构造函数接收两个函数作为参数,分别是resolve和reject,
当异步操作执行成功后,会将异步操作结果作为参数传入resolve函数并执行,此时 Promise对象状态从pending变为resolve;
失败则会将异步操作的错误作为参数传入reject函数并执行,此时 Promise对象状态从pending变为rejected;

相关API:
all()
这个方法会返回一个新的promise对象,如果里面所有的promise对象都成功才会触发,一旦有一个失败,则该promise对象为失败
写法:
const arr = Promise.arr()

race()
当参数中的任意一个promise对象完成时候,就马上回去使用完成的这个promise对象的结果,不管这个结果成功还是失败
写法
const arr = Promise.race()

Promise原型:
Promise 的实例具有 then 方法,主要作用是为 Promise 实例发生状态改变时添加回调函数,
Promise的catch主要返回一个Promise,并且处理拒绝的情况。
Promise的finally()指上一次promise 运行结束后,无论resolved还是 rejected,都会执行指定的回调函数。
代码演示一个基本的一个Promise

 <script type="text/javascript">
	  	 const arr = [];
	  	 for(let i = 0 ; i < 5; i++){
	  	 	arr.push(new Promise(resolve , reject) => {
	  	 		//设置一个一次性定时器
	  	 		setTimeout(() => {
	  	 			//判断结果
	  	 			if(Math.random() < 0.1){
	  	 				console.log('成功')
	  	 				resolve(i)
	  	 			}else{
	  	 				console.log('失败')
	  	 				reject(i)
	  	 			}
	  	 		},1000)
	  	 	})
	  	 }
	  	 const pro = Promise.race(arr);
	  	 pro.then(data => {
	  	 	console.log('完成' + data)
	  	 })
	  	 pro.catch(err => {
	  	 	console.log('未完成' + err)
	  	 })
	  </script>
<think>嗯,用户想了解如何手动实现JavaScript的Promise。首先,我得回忆一下Promise的基本工作原理。Promise是用于处理异步操作的对象,有三种状态:pending、fulfilled和rejected。状态一旦改变就不能再变。 首先,我需要定义一个类,比如MyPromise。构造函数接收一个执行器函数,执行器里会调用resolve和reject。这两个函数需要改变状态,并且处理回调。因为then方法可以多次调用,所以需要存储回调函数,可能用数组来保存。 然后,resolve和reject函数要负责改变状态,并且执行相应的回调。这里要注意,异步操作完成后才会触发回调,所以可能需要用setTimeout或者微任务机制来异步执行回调。不过手动实现的话,可能先用setTimeout模拟。 接下来是then方法的实现。then方法需要接收onFulfilled和onRejected两个参数,并且返回一个新的Promise,以实现链式调用。这时候要考虑如果onFulfilled不是函数的话,应该设置默认函数,将值传递下去。同时,需要处理回调的执行结果,如果是Promise的话,需要等待它的状态改变。 另外,错误处理也很重要。如果在执行过程中抛出异常,应该捕获并传递给下一个reject。比如在执行器函数或者then的回调中出现的错误,都需要被正确处理。 还要处理同步和异步的情况。比如,如果执行器里同步调用了resolve,那么then方法添加的回调应该还是异步执行。这可能需要用队列来管理回调,确保它们按顺序执行。 可能还需要实现catch方法,其实就是then方法的特例,只处理rejected的情况。还有finally方法,不过用户的问题可能暂时不需要这个。 测试的时候,用户给出的例子中有多个then调用,并且有setTimeout。所以在实现时,必须确保then的回调在resolve被调用后才会执行,并且多个then的回调都能被正确触发。 此外,链式调用中的返回值如果是Promise,需要等待它解决。这部分可能需要递归处理,直到得到一个非Promise的值,或者最终状态。 可能遇到的难点包括状态管理的原子性,确保一旦状态改变就不会再变,以及正确处理异步回调的顺序。还有链式调用中每个then返回新Promise的处理逻辑,需要正确地将前一个的结果传递给下一个。 总结步骤大概是: 1. 定义MyPromise类,初始化状态和值。 2. 实现resolve和reject方法,改变状态并执行回调。 3. 实现then方法,收集回调,返回新Promise。 4. 处理回调的返回值,支持链式调用。 5. 错误处理和异步执行。 需要参考用户提供的引用,比如引用[3]中的例子,确保实现的MyPromise能正确处理多个then的调用,并在setTimeout后执行。同时,引用[2]提到then返回Promise,所以链式调用需要正确处理返回的Promise。 可能还需要实现其他方法如catch和静态方法如resolve、reject、all等,但根据用户的问题,主要关注then和基本结构。 最后,代码示例要符合规范,正确使用$和$$格式,确保LaTeX语法正确,比如在提到状态时用$...$包裹变量。</think>### 手动实现 JavaScript Promise 的方法 #### 1. Promise 的核心原理 Promise 是用于管理异步操作的对象,包含三种状态:$pending$(等待)、$fulfilled$(成功)和$rejected$(失败)。状态一旦改变不可逆。实现需满足以下特性: - **链式调用**:通过 `then` 方法返回新 Promise 实现链式操作[^2] - **异步执行**:回调函数需异步触发(如通过 `setTimeout` 模拟微任务) - **错误冒泡**:若未定义错误处理,错误会向下传递直到被捕获 #### 2. 基础框架实现 ```javascript class MyPromise { constructor(executor) { this.state = 'pending'; // 初始状态 this.value = undefined; // 成功值/失败原因 this.onFulfilledCallbacks = []; // 成功回调队列 this.onRejectedCallbacks = []; // 失败回调队列 const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn()); // 异步触发回调 } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.value = reason; this.onRejectedCallbacks.forEach(fn => fn()); } }; try { executor(resolve, reject); // 立即执行执行器函数 } catch (err) { reject(err); // 捕获同步错误 } } } ``` #### 3. `then` 方法实现 ```javascript then(onFulfilled, onRejected) { // 默认值穿透处理 onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v; onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }; const promise2 = new MyPromise((resolve, reject) => { const handleCallback = (callback, value) => { setTimeout(() => { // 模拟微任务 try { const x = callback(value); resolvePromise(promise2, x, resolve, reject); } catch (err) { reject(err); } }); }; if (this.state === 'fulfilled') { handleCallback(onFulfilled, this.value); } else if (this.state === 'rejected') { handleCallback(onRejected, this.value); } else { // pending 状态时存储回调 this.onFulfilledCallbacks.push(() => handleCallback(onFulfilled, this.value)); this.onRejectedCallbacks.push(() => handleCallback(onRejected, this.value)); } }); return promise2; // 返回新 Promise 实现链式调用 } ``` #### 4. 解决回调返回值 ```javascript function resolvePromise(promise2, x, resolve, reject) { if (x === promise2) { return reject(new TypeError('Chaining cycle detected')); } if (x instanceof MyPromise) { x.then(resolve, reject); // 递归处理 Promise 返回值 } else { resolve(x); // 直接传递普通值 } } ``` #### 5. 测试用例 ```javascript const p = new MyPromise((resolve) => { setTimeout(() => resolve("ok"), 1000); }); p.then(res => console.log(res + 1)) // 输出 "ok1" .then(() => new MyPromise(resolve => resolve(100))) .then(num => console.log(num)); // 输出 100 ``` #### 关键点总结 - **状态隔离**:每个 `then` 返回的新 Promise 独立管理状态 - **异步队列**:通过回调队列处理异步操作和多次调用 `then` 的场景[^3] - **错误处理**:通过 `try/catch` 捕获同步/异步错误 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值