实现一个Promise

本文通过分析Promise的使用方式,逐步实现了一个名为MyPromise的简易版本,探讨了Promise的状态变化、then方法的处理及异步执行的实现,以加深对Promise原理的理解。在实现过程中,重点解决了状态不可逆、值穿透、异步调用等问题,并通过测试用例验证了MyPromise的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现一个Promise

Promise是异步请求的一种解决方案,不同于传统的回调函数,它通过链式调用很好的解决了回调地狱,让异步执行清晰明了。在实际开发中也经常使用Promise,那Promise内部是如何实现的呢?

我们通过Promise的使用方式为突破口,实现一个Promise,为了与Promise区分,我们实现的Promise称它为MyPromise。

// Promise使用
let promise = new Promise((resolve, reject) => {
	// TODO
	// fulfilled => resolve(value)
	// rejected => reject(reason)
})

上面是创建Promise实例最常用的写法,通过使用Promise,我们知道它有3个状态:pending、fulfilled、rejected,且状态只能由pending转变为fulfilled或pending转变为rejected,转变之后不能再变化,如:pending转变成fulfilled之后不能再变成rejected,也就是Promise状态变化不可逆。

我们通过new关键词生成一个Promise实例,可以看出Promise会接收一个函数(我们暂时称它为executor函数)作为参数,Promise实例生成后executor函数会被调用,也就是该函数内的代码被执行,executor函数接收resolve和reject两个参数,当Promise状态从pending转变成fulfilled时,会调用resolve函数,并传入状态变为fulfilled后的返回值value作为参数;当状态变成rejected时,调用reject函数,并传入状态变为rejected后的返回值reason作为参数。

通过上述分析,我们可以将MyPromise写成如下:

// MyPromise的三种状态
let PENDING = 'pending'
let FULFILLED = 'fulfilled'
let REJECTED = 'rejected'

function MyPromise(executor) {
	let that = this
	that.status = PENDING // 初始状态
	that.value = undefined // 状态变成fulfilled后resolve的值
	that.reason = undefined // 状态变成rejected后reject的原因
	
	// 定义executor函数的参数resolve
	function resolve(value) {
		// TODO
		if(that.status === PENDING){
			that.status = FULFILLED
			that.value = value
		}
	}
	
	// 定义executor函数的参数reject
	function reject(reason) {
		// TODO
		if(that.status === PENDING){
			that.status = REJECTED
			that.reason = reason
		}
	}
	
	// 执行executor函数
	try{
		executor(resolve, reject)
	} catch(e) {
		reject(e)
	}
}

上面我们搭建了MyPromise的基本框架,继续分析Promise的使用来完善MyPromise

// Promise使用

// 状态为fulfilled的Promise实例
let promise = new Promise((resolve, reject) => {
	resolve(1)
})
// Promise实例具有then方法
let promise1 = promise.then((res) => {
	console.log(res)
	return res
}, (e) => {
	console.log(e)
})
// 1

// Promise实例调用then方法后也返回一个Promise实例,且与之前的实例不同
promise1.then((res) => {
	console.log(res)
})
// 1

promise === promise1
// false

// Promise实例then方法具有值穿透的功能
promise.then().then((res) => {
	console.log(res)
})
// 1

// 状态为rejected的Promise实例
let promise2 = new Promise((resolve, reject) => {
	reject(2)
})
let promise3 = promise2.then((res) => {
	console.log(res)
}, (e) => {
	console.log(e)
})
// 2

上面可以看出:1、Promise实例调用then方法后返回一个新的Promise实例,与之前的实例不是同一个东西;2、当then方法中参数为空时,then方法具有值穿透的功能;3、Promise实例都有then方法,then方法可以接收两个参数(我们暂时称它们分别为onFulfilled、onRejected),当Promise实例状态为fulfilled时,调用其then方法会执行onFulfilled函数,状态为rejected时,调用onRejected函数,当Promise实例状态为pending时,会将onFulfilled和onRejected函数分别添加到onFulfilledCallback和onRejectedCallback数组中,等待Promise实例状态转变,然后执行其对应的回调;

functon MyPromise(executor) {
	...
	that.onFulfilledCallback = [] // 存放当前状态为pending,状态如果转变为fulfilled时执行的回调onFulfilled
	that.onRejectedCallback = [] // 存放当前状态为pending,状态如果转变为rejected时执行的回调onRejected

	function resolve(value) {
		if(that.status === PENDING){
			...
			that.onFulfilledCallback.forEach(cb => cb(that.value)) // 状态从pending转变为fulfilled时,执行其对应的onFulfilled回调
		}
	}
	
	function reject(reason) {
		if(that.status === PENDING){
			...
			that.onRejectedCallback.forEach(cb => cb(that.reason)) // 状态从pending转变为rejected时,执行其对应的onRejected回调
		}
	}
	...
}

MyPromise.prototype.then = function (onFulfilled, onRejected){
	let that = this
	let promise1 // then方法要返回的新的实例
	onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value // 当onFulfilled为空或者不为函数时让其具有值穿透功能
	onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
	// 当状态为fulfilled时,执行onFulfilled方法
	if(that.status === FULFILLED){
		// 返回一个新的MyPromise实例,并根据onFulfilled回调执行结果将结果resolve或reject出来
		return promise1 = new MyPromise((resolve, reject) => {
			// 状态为fulfilled时,执行then方法中onFulfilled函数的结果
			let x = onFulfilled(that.value)
			// x的结果可能是一个promise、也可能是一个带有then方法的对象、也可能是一个普通对象、也可能是一个普通值,为了处理x值多种情况,通过resolvePromise方法对上述情况做统一处理
			resolvePromise(promise1, x, resolve, reject)
		})
	}
	// 当状态为rejected时,执行onRejected方法
	if(that.status === REJECTED){
		return promise1 = new MyPromise((resolve, reject) => {
			// 状态为rejected时,执行then方法中onRejected函数的结果
			let x = onRejected(that.reason)
			resolvePromise(promise1, x, resolve, reject)
		})
	}
	// 当状态为pending时,将onFulfilled和onRejected方法分别添加到onFulfilledCallback和onRejectedCallback数组中,等待状态变化时执行对应回调
	if(that.status === PENDING){
		return promise1 = new MyPromise((resolve, reject) => {
			that.onFulfilledCallback.push((value) => {
				let x = onFulfilled(value)
				resolvePromise(promise1, x, resolve, reject)
			})
			that.onRejectedCallback.push((reason) => {
				let x = onRejected(reason)
				resolvePromise(promise1, x, resolve, reject)
			})
		})
	}
}

function resolvePromise(promise, x, resolve, reject){
	if(promise === x){
		return reject(new TypeError('循环引用'))
	}
	let called = false // 当x为含有then方法的对象或函数时,防止x.then方法被多次调用
	if(x instanceof MyPromise){ // x为MyPromise实例
		if(x.status === PENDING){ // 当x状态为pending时,等待其状态转变为fulfilled时解析x返回值y或状态转变成rejected时执行reject回调
			x.then(y => {
				resolvePromise(promise, y, resolve, reject)
			}, reason => {
				reject(reason)
			})
		} else { // 当x状态为fulfilled或rejected时,通过then方法执行resolve或reject回调
			x.then(resolve, reject)
		}
	} else if(x != null && (typeof x === 'object' || typeof x === 'function')){ // x为非空的对象或函数时
		let then = x.then
		if(typeof then === 'function'){ // x为含有then方法的对象或函数,等待x的执行结果,当x状态为fulfilled时,执行resolvePromise解析其返回值y,当x状态为rejected时,执行reject回调
			then.call(x, y => {
				if(called) return
				called = true
				resolvePromise(promise, y, resolve, reject)
			}, reason => {
				if(called) return
				called = true
				reject(reason)
			})
		} else { // x为普通的对象或函数
			resolve(x)
		}
	} else { // x为普通值时,如:string、boolean、number等
		resolve(x)
	}
}

上述代码中完成了MyPromise的then方法,但是还有一个明显的问题没有解决,那就是MyPromise实例的执行顺序。

继续看如下代码:

// Promise使用
console.log('start')
let promise = new Promise((resolve, reject) => {
	console.log(1)
	resolve(1)
})
promise.then((res) => {
	console.log(res + 1)
})
console.log('end')
// start
// 1
// end 
// 2

从上述的执行结果可以看出,resolve之后,then方法中onFulfilled函数的执行是在当前事件循环结束后才执行,也就是onFulfilled的执行是异步的,为了保证MyPromise的执行顺序与Promise一致,需要在resolve、reject方法执行时通过setTimeout将其变为异步执行(这些是针对状态是pending的情况,对于状态已经是fulfilled或rejected的实例,为了保证then方法中的onFulfilled或onRejected异步执行,还需要在then方法中做处理),具体如下:

functon MyPromise(executor) {
	...
	function resolve(value) {
		setTimeout(() => {
			if(that.status === PENDING){
				...
			}
		})		
	}
	
	function reject(reason) {
		setTimeout(() => {
			if(that.status === PENDING){
				...
			}
		})
	}
	...
}

MyPromise.prototype.then = function (onFulfilled, onRejected){
	...
	if(that.status === FULFILLED){
		return promise1 = new MyPromise((resolve, reject) => {
			setTimeout(() => {
				let x = onFulfilled(that.value)
				resolvePromise(promise1, x, resolve, reject)
			})
		})
	}
	if(that.status === REJECTED){
		return promise1 = new MyPromise((resolve, reject) => {
			setTimeout(() => {
				let x = onRejected(that.reason)
				resolvePromise(promise1, x, resolve, reject)
			})
		})
	}
	...
}

至此,MyPromise的实现基本就完成了,贴上完整的代码,如下:

// MyPromise的三种状态
let PENDING = 'pending'
let FULFILLED = 'fulfilled'
let REJECTED = 'rejected'

function MyPromise(executor) {
	let that = this
	that.status = PENDING // 初始状态
	that.value = undefined // 状态变成fulfilled后resolve的值
	that.reason = undefined // 状态变成rejected后reject的原因
	that.onFulfilledCallback = [] // 存放当前状态为pending,状态如果转变为fulfilled时执行的回调onFulfilled
	that.onRejectedCallback = [] // 存放当前状态为pending,状态如果转变为rejected时执行的回调onRejected
	
	// 定义executor函数的参数resolve
	function resolve(value) {
		if(value instanceof MyPromise){
			value.then(resolve, reject)
		}
		setTimeout(() => {
			if(that.status === PENDING){
				that.status = FULFILLED
				that.value = value
				that.onFulfilledCallback.forEach(cb => cb(that.value)) // 状态从pending转变为fulfilled时,执行其对应的onFulfilled回调
			}
		})
	}
	
	// 定义executor函数的参数reject
	function reject(reason) {
		setTimeout(() => {
			if(that.status === PENDING){
				that.status = REJECTED
				that.reason = reason
				that.onRejectedCallback.forEach(cb => cb(that.reason)) // 状态从pending转变为rejected时,执行其对应的onRejected回调
			}
		})
	}
	
	// 执行executor函数
	try{
		executor(resolve, reject)
	} catch(e) {
		reject(e)
	}
}
MyPromise.prototype.then = function (onFulfilled, onRejected){
	let that = this
	let promise1 // then方法要返回的新的实例
	onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value // 当onFulfilled为空或者不为函数时让其具有值穿透功能
	onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
	// 当状态为fulfilled时,执行onFulfilled方法
	if(that.status === FULFILLED){
		// 返回一个新的MyPromise实例,并根据onFulfilled回调执行结果将结果resolve或reject出来
		return promise1 = new MyPromise((resolve, reject) => {
			setTimeout(() => {
				try{
					// 状态为fulfilled时,执行then方法中onFulfilled函数的结果
					let x = onFulfilled(that.value)
					// x的结果可能是一个promise、也可能是一个带有then方法的对象、也可能是一个普通对象、也可能是一个普通值,为了处理x值多种情况,通过resolvePromise方法对上述情况做统一处理
					resolvePromise(promise1, x, resolve, reject)
				} catch(e){
					reject(e)
				}
			})
		})
	}
	// 当状态为rejected时,执行onRejected方法
	if(that.status === REJECTED){
		return promise1 = new MyPromise((resolve, reject) => {
			setTimeout(() => {
				try{
					// 状态为rejected时,执行then方法中onRejected函数的结果
					let x = onRejected(that.reason)
					resolvePromise(promise1, x, resolve, reject)
				} catch(e){
					reject(e)
				}
			})
		})
	}
	// 当状态为pending时,将onFulfilled和onRejected方法分别添加到onFulfilledCallback和onRejectedCallback数组中,等待状态变化时执行对应回调
	if(that.status === PENDING){
		return promise1 = new MyPromise((resolve, reject) => {
			that.onFulfilledCallback.push((value) => {
				try{
					let x = onFulfilled(value)
					resolvePromise(promise1, x, resolve, reject)
				} catch(e){
					reject(e)
				}
			})
			that.onRejectedCallback.push((reason) => {
				try{
					let x = onRejected(reason)
					resolvePromise(promise1, x, resolve, reject)
				} catch(e){
					reject(e)
				}
			})
		})
	}
}

function resolvePromise(promise, x, resolve, reject){
	if(promise === x){
		return reject(new TypeError('循环引用'))
	}
	let called = false // 当x为含有then方法的对象或函数时,防止x.then方法被多次调用
	if(x instanceof MyPromise){ // x为MyPromise实例
		if(x.status === PENDING){ // 当x状态为pending时,等待其状态转变为fulfilled时解析x返回值y或状态转变成rejected时执行reject回调
			x.then(y => {
				resolvePromise(promise, y, resolve, reject)
			}, reason => {
				reject(reason)
			})
		} else { // 当x状态为fulfilled或rejected时,通过then方法执行resolve或reject回调
			x.then(resolve, reject)
		}
	} else if(x != null && (typeof x === 'object' || typeof x === 'function')){ // x为非空的对象或函数时
		try{
			let then = x.then
			if(typeof then === 'function'){ // x为含有then方法的对象或函数,等待x的执行结果,当x状态为fulfilled时,执行resolvePromise解析其返回值y,当x状态为rejected时,执行reject回调
				then.call(x, y => {
					if(called) return
					called = true
					resolvePromise(promise, y, resolve, reject)
				}, reason => {
					if(called) return
					called = true
					reject(reason)
				})
			} else { // x为普通的对象或函数
				resolve(x)
			}
		} catch(e){
			if(called) return
			called = true
			reject(e)
		}
	} else { // x为普通值时,如:string、boolean、number等
		resolve(x)
	}
}

最后通过promises-aplus-tests来测试我们写的MyPromise,promises-aplus-tests提供了很多测试用例,通过跑这些测试用例可以验证我们MyPromise是否正确,具体如下:

1、在MyPromise上添加一个延迟属性deferred,并将MyPromise导出

MyPromise.deferred = function () {
	let defer = {}
	defer.promise = new MyPromise((resolve, reject) => {
    	defer.resolve = resolve
    	defer.reject = reject
  	})
  	return defer
}

try{
  	module.exports = MyPromise
} catch(e){
  	throw new Error(e)
}

2、安装并执行promises-aplus-tests

npm i -g promises-aplus-tests
promises-aplus-tests MyPromise.js

测试用例全部通过
在这里插入图片描述

参考文献:

[1] Promise原理讲解 && 实现一个Promise对象 (遵循Promise/A+规范)
[2] Promise实现原理(附源码)
[3] 剖析Promise内部结构,一步一步实现一个完整的、能通过所有Test case的Promise类

<think>我们来实现一个简单的Promise,遵循Promise/A+规范的核心部分。由于完整实现较为复杂,这里我们实现一个简化版,包含基本功能:状态管理、then方法、异步执行支持。 核心要点: 1. Promise有三种状态:pending, fulfilled, rejected 2. 初始化时传入一个执行器函数(executor),该函数立即执行,接收两个参数:resolve和reject 3. then方法用于注册回调,当状态改变时调用对应的回调 4. 支持异步:当状态还未改变时,将回调暂存,待状态改变后执行 我们将按照以下步骤实现: 1. 定义状态常量 2. 构造函数:初始化状态、值、原因以及回调队列 3. 实现resolve和reject内部函数 4. 实现then方法 5. 处理executor中的异常 注意:此实现不包含链式调用(即then返回新的Promise)和值穿透等高级特性,仅提供基本功能。 代码实现:</think>### 简单实现一个 Promise #### 基础版 Promise 实现(符合 Promise/A+ 规范核心部分) ```javascript class MyPromise { constructor(executor) { this.state = 'pending'; // 状态: pending, fulfilled, rejected this.value = null; // 成功时的值 this.reason = null; // 失败时的原因 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.reason = reason; // 执行所有失败回调 this.onRejectedCallbacks.forEach(fn => fn()); } }; try { // 立即执行执行器函数 executor(resolve, reject); } catch (error) { // 捕获执行器中的异常 reject(error); } } then(onFulfilled, onRejected) { // 处理值穿透 onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; }; // 返回新Promise实现链式调用 return new MyPromise((resolve, reject) => { const handleFulfilled = () => { try { const result = onFulfilled(this.value); resolve(result); } catch (error) { reject(error); } }; const handleRejected = () => { try { const result = onRejected(this.reason); resolve(result); } catch (error) { reject(error); } }; if (this.state === 'fulfilled') { // 异步执行 setTimeout(handleFulfilled, 0); } else if (this.state === 'rejected') { setTimeout(handleRejected, 0); } else { // pending状态 this.onFulfilledCallbacks.push(() => setTimeout(handleFulfilled, 0)); this.onRejectedCallbacks.push(() => setTimeout(handleRejected, 0)); } }); } // 简单实现catch方法 catch(onRejected) { return this.then(null, onRejected); } // 简单实现finally方法 finally(callback) { return this.then( value => MyPromise.resolve(callback()).then(() => value), reason => MyPromise.resolve(callback()).then(() => { throw reason; }) ); } // 静态resolve方法 static resolve(value) { if (value instanceof MyPromise) return value; return new MyPromise(resolve => resolve(value)); } // 静态reject方法 static reject(reason) { return new MyPromise((_, reject) => reject(reason)); } } ``` #### 使用示例 ```javascript // 基本使用 const p1 = new MyPromise((resolve, reject) => { setTimeout(() => resolve('成功!'), 1000); }); p1.then(result => { console.log(result); // 1秒后输出"成功!" return '链式调用'; }).then(msg => { console.log(msg); // 输出"链式调用" }); // 错误处理 const p2 = new MyPromise((resolve, reject) => { reject(new Error('出错了!')); }); p2.catch(error => { console.error(error.message); // 输出"出错了!" }); // 静态方法 MyPromise.resolve('立即解析') .then(console.log); // 输出"立即解析" MyPromise.reject('立即拒绝') .catch(console.error); // 输出"立即拒绝" ``` #### 实现要点解析 1. **状态机设计** - 三种状态:`pending`、`fulfilled`、`rejected` - 状态单向转换:`pending` → `fulfilled` 或 `pending` → `rejected` 2. **异步处理** - 使用 `setTimeout` 确保回调异步执行 - 回调队列处理异步操作完成前的多次 `then` 调用 3. **链式调用** - `then` 方法返回新 Promise 对象 - 值穿透处理:`then(null, ...)` 和 `catch` 实现 4. **错误处理** - 执行器函数错误捕获 - 回调函数错误传播 #### 与原生 Promise 的差异 | 特性 | 原生 Promise | 本实现 | |--------------------|----------------------|---------------------| | 微任务队列 | 使用微任务 | 使用宏任务(setTimeout) | | Promise.all | 支持 | 未实现 | | Promise.race | 支持 | 未实现 | | 性能优化 | 高度优化 | 基础实现 | | 规范符合度 | 完整 Promise/A+ | 核心部分 | #### 进阶扩展建议 1. **实现 Promise.all** ```javascript static all(promises) { return new MyPromise((resolve, reject) => { const results = []; let completed = 0; promises.forEach((promise, index) => { MyPromise.resolve(promise).then( value => { results[index] = value; if (++completed === promises.length) resolve(results); }, reject // 任一失败立即reject ); }); }); } ``` 2. **实现 Promise.race** ```javascript static race(promises) { return new MyPromise((resolve, reject) => { promises.forEach(promise => { MyPromise.resolve(promise).then(resolve, reject); }); }); } ``` 3. **添加取消功能** ```javascript constructor(executor) { // ...其他代码... this.isCancelled = false; const cancel = () => { this.isCancelled = true; reject(new Error('Promise cancelled')); }; executor(resolve, reject, cancel); // 添加取消函数 } // 使用 const p = new MyPromise((resolve, reject, cancel) => { // 设置取消函数 window.cancelRequest = cancel; }); ``` #### 应用场景 1. **API请求封装** ```javascript function fetchData(url) { return new MyPromise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onload = () => resolve(JSON.parse(xhr.responseText)); xhr.onerror = () => reject(new Error('Request failed')); xhr.send(); }); } ``` 2. **异步流程控制** ```javascript MyPromise.resolve() .then(() => loadUserData()) .then(user => loadOrders(user.id)) .then(orders => processOrders(orders)) .catch(handleError); ``` 3. **超时控制** ```javascript function withTimeout(promise, timeout) { return MyPromise.race([ promise, new MyPromise((_, reject) => setTimeout(() => reject(new Error('Timeout')), timeout) ) ]); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值