手写Promise,一步步实现自己的Promise

一、什么是Promise

promis是异步工作解决方案,是callback回调的替代方案,通过new实例化对象,所以本质是一个构造方法。内部有三种状态: pending(进行中)、fulfilled(成功)、rejected(失败)。

提供的方法:
Promise A+ 规范.

  • then () {} // 执行成功后的回调

es6 规范 贴个使用地址

  • catch(onRejected) { } // Promise 失败时候的回调
  • finally (onFinally) {} // Promise 不管失败还是成功的回调
  • static resolve(result) { } // 更改Promise状态为 fulfilled, 执行then和finally方法结束当前Promise
  • static reject (error) {} // 更改Promise状态为rejected,执行catch和finally方法结束当前Promise
  • 其他,后面再说

1Promise的使用方式(可能会发生的情况)

1.1 、只创建,不传入回调方法

控制台报错
eslint报错

1.2、创建 调用resolve 回调会抛错

const p = new Promise((resolve, reject) => {
	resolve(123);
}).then(res => {
	// 成功返回后干嘛干嘛
}).finally(() => {
	// 不管成功还是失败都返回,并且没有参数
})

在这里插入图片描述

1.3 、创建 调用reject回调,并且调用catch 或者then 方法传入了失败的回调, 返回的是 fulilled状态

const p = new Promise((resolve, reject) => {
	reject(123);
}).catch(res => {
	// 失败返回后干嘛干嘛
}).finally(() => {
	// 不管成功还是失败都返回,并且没有参数
})
const p = new Promise((resolve, reject) => {
	reject(123);
}).then(res => {

}, err => {
	// 失败回调
})

有catch,会返回fulfilled状态

1.4、创建 调用reject回调,不调用catch, 返回的是rejected状态 与3不同

在这里插入图片描述

1.5、内部抛错 和4一样,此时会走catch方法

const p = new Promise((resolve, reject) => {
	throw 123;
})

1.6、 存在异步函数 返回的是 pending状态,不会走catch方法,也不会走finally方法

const p = new Promise((resolve, reject) => {
	setTimeout(() => {
        throw 123;
    }, 0)
})

1.7、 return 返回 与6 相同 pending状态,不会走then方法,也不会走finally方法

const p = new Promise((resolve, reject) => {
	return 123
})

1.8 、多次调用resolve 或者 reject, 由第一个调用为准

const p = new Promise((resolve, reject) => {
	resolve(123);
	reject(123);
})

二、开始实现

2.1 定义MyPromise

常规Promise 用法是 new 出来的,所以需要先顶一个构造器,并且传入的是一个回调函数,最终实现的是内部调用传入的方法与浏览器微任务有关,下文讲到,并且传入 Promise内部返回出来的resolve和reject方法

// 原始promise 使用方式
const promise = new Promise((resolve, rejeck) => {
	// 这里可以传入参数
	resolve(123);
})
// ------------------自己的promise 开始-------------------
// 定义回调函数,会被Promise自动执行
function callback (resolve, reject) {}

class MyPromise {
	// jiejue 
	// executor 是外部传入的
	constructor(executor) {
		// 解决 目录1.1 报错问题,不传或者传的不是function
		if (typeof executor !== 'function') {
			throw new TypeError(`Promise resolver ${executor} is not a function`) 
		}
		// 外部会调用方法并传入参数,不传就是undefind
		const resolve = (data) => {}
		const reject= (error) => {}
		// 内部定义resolve/reject 返回出去
		executor(resolve, reject)
	}
}
const p = new MyPromise(callback);

2.2 定义Promise返回的状态和数据

promise 返回的一个是状态,一个是返回的结果

const PENDING= 'pending';
const FULFILLED= 'fulfilled';
const REJECTED= 'rejected';

class MyPromise {
	// 私有属性外部不让用,用新出来的#前缀修饰
	//用 typescript 可以用 private
	// 默认是pending状态
	#state = PENDING;
	// 定义结果,默认是undefined
	#result = undefined;

	// 省略下面部分
}

2.3 实现resolve / reject方法

注意:由于promise内部resolve和reject和重复调用,并且状态只会被更新一次,需要判断一下当前状态

class MyPromise {
	// 省略上卖弄部分
	constructor(executor) {
		// 省略上面
		const resolve = (data) => {
			// 判断是否被执行resolve或reject
			if (this.#state !== PENDING) return;
			// 状态置为fulfilled
			this.#state = FULFILLED;
			// 结果置为data
			this.#result = data;
		}
		const reject= (error) => {
			// 判断是否被执行resolve或reject
			if (this.#state !== PENDING) return;
			// 状态置为fulfilled
			this.#state = REJECTED;
			// 结果置为data
			this.#result = error;
		}
		// 省略下面
	}
}

2.4 抽离改变状态方法,解决promise 内部 throw的问题

 // 由于更改状态的代码相似,抽一个方法出来
 class MyPromise {
	constructor(executor) {
		// 省略上面
		const resolve= (data) => {
			this.#updateState(FULFILLED, data)
		}
		const reject= (error) => {
			this.#updateState(REJECTED, error)
		}
		/* 解决 内部报错问题 用try catch 包裹
		 new Promise(() => {
				throw 123
			})
		*/
		// 注意:这里只能捕捉到同步错误,内部如果是setTimeout 返回的异步代码是捕捉不到的
		try {
			executor(resolve, reject)
		} catch (error) {
			// 报错 内部调用reject方法
			reject(error)
		}
	}
	// 传入状态和 结果// 统一入口,下面会用到
	#updateState (state, result) {
		if (this.#state !== PENDING) return;
		this.#state = state;
		this.#result = result;
	}
}

注意:这里实现的效果有

  1. 目录1.1 报错效果
  2. 目录1.8重复调用resolve只会更改一次状态效果
  3. 目录throw后 会走catch方法效果,catch方法下面实现

2.5 实现Promise A+ 规范,then方法

Promise A+ 规范 并未说明 怎么样算一个Promise,只需要一个对象或者方法带有then方法,他就认为你就是promise,就可以和自生交互
then 方法 特点

  1. 有2个参数 onFulfilled 和 onRejected, 可以是任意值
  2. 如果onFulfilled/onRejected 传入的不是一个函数,那么此时的状态和当前Promise一致
  3. 返回的是一个新的promise

class MyPromise {
	// 有2个参数 onFulfilled 和 onRejected
	then (onFulfilled, onRejected) {
		// 返回一个新的promise,
		return new MyPromise((resolve, reject) => {
			// 1.解决什么时候调用onFulfilled / onRejected
			if (this.#state === FULFILLED) {
				// onFulfilled 可以是任意值,需要判断是否是函数
				if (typeof onFulfilled === 'function') {
					onFulfilled(this.#result)
				} else {/*先留着*/ }
			} else if (this.#state === REJECTED) {
			/	/ onRejected可以是任意值,需要判断是否是函数
				if (typeof onRejected=== 'function') {
					onRejected(this.#result)
				} else {/*先留着*/ }
			} else {
				// 如果这里是异步的 这么办?????
				/*
				setTimeout(() =. {
					resolve(12323)
				}, 1000)
				*/
			}
		})
	}
}
const p = new MyPromise((resolve, reject) => {
	resolve(123)
})
p.then((res) => {
	console.log('promise 成功', res)
}, (err) => {
	console.log('promise 失败', err)
})

2.6 解决异步函数内 resolve 无法被then捕捉问题

要解决2.5问题,

  1. 首先要知道 什么时候执行onFulfilled/onRejected方法??
    回答是当状态变化的时候,也就是#updateState里面去执行
  2. 状态变化时怎么知道 2.5 提到 onFulfilled/onRejected 方法,怎么知道返回新的promise里面的resolve/reject方法?
    方法是 先找个地方存起来
class MyPromise {
	// 保存当前then方法里面的方法地址,考虑到then方法可以被多次调用,并且每个then返回 结果都市一样的,这里要设置成一个数组
	#currentThenParams = [];
	#handlerThenFn () {
		// 当前状态没有变更就不执行
		if (this.#state === FULFILLED) return;
		while (this.#currentThenParams.length) {
			// 每次弹出一个去执行
			const { onFulfilled,
				onRejected,
				resolve,
				reject } = this.#currentThenParams.shift();
		}
		if (this.#state === FULFILLED) {
			// onFulfilled 可以是任意值,需要判断是否是函数
			if (typeof onFulfilled === 'function') {
 				// 调用onFulfilled 会有返回值,需要重新resolve出去
				const result = onFulfilled(this.#result);
				resolve(result )
			} else {
				// 走到这里说明传进来的是其他值,应该和resolve返回一致 的结果
				resolve(this.#result)
			}
		} else if (this.#state === REJECTED) {
			// onRejected可以是任意值,需要判断是否是函数
			if (typeof onRejected=== 'function') {
				// 调用onFulfilled 会有返回值,需要重新reject出去
				const result = onRejected(this.#result)
				reject(result )
			} else {
				// 走到这里说明传进来的是其他值,应该和resolve返回一致 的结果
				reject(this.#result)
			}
		}
	}
	// 传入状态和 结果// 统一入口,下面会用到
	#updateState (state, result) {
		if (this.#state !== PENDING) return;
		this.#state = state;
		this.#result = result;
		this.#handlerThenFn()
	}
	// 有2个参数 onFulfilled 和 onRejected
	then (onFulfilled, onRejected) {
		// 返回一个新的promise,
		return new MyPromise((resolve, reject) => {
			// 把所有方法的地址存起来
			this.#currentThenParams.push({
				onFulfilled,
				onRejected,
				resolve,
				reject
			})
			this.#handlerThenFn()
		})
	}
}
const p = new MyPromise((resolve, reject) => {
	setTimeout(() => {
		resolve(123)
	})
})
p.then((res) => {
	console.log('promise 成功', res)
}, (err) => {
	console.log('promise 失败', err)
}).then((res) => {
	console.log('promise 成功11', res)
}, (err) => {
	console.log('promise 失败11', err)
})

到这里已经实现了可以链式调用then方法了,而且能顺利调用每一个回调,但是还有不少缺陷

  1. const result = onRejected(this.#result) 假如传入的是新promise,那么result 是一个promise,不能直接返回
  2. 假如onRejected(this.#result) 执行时候报错了,那就需要reject 出去,这个不会执行
  3. Promise应该是一个微任务,到这里度只是同步执行,用console.log 可以试验一下
	console.log('我是最先执行的')
	new MyPromise((resolve) => {
		resolve('我是MyPromise')
	}).then(res => {
		console.log(res )
	})
	console.log('照道理我是第二个执行的')

执行结果

2.7 解决onFulfilled (this.#result) 过程中有报错的情况

用try catch 包裹即可 onRejected 同理

if (typeof onFulfilled === 'function') {
	try {
		// 调用onFulfilled 会有返回值,需要重新reject出去
		const result = onFulfilled(this.#result)
		resolve(result ); // 这里是resolve
	} catch (error) {
		reject(error) // 这里是reject
	}} 
}
if (typeof onRejected=== 'function') {
	try {
		// 调用onFulfilled 会有返回值,需要重新reject出去
		const result = onRejected(this.#result)
		resolve(result ); // 这里resolve
	} catch (error) {
		reject(error); // reject
	}} 
}

2.8 解决返回的是promise的问题,解决promise 互操作性

Promise A+ 规范里面提到的,只要你带有then方法,那就可以和Promise互操作

首先定义一个类promise方法入口,统一判断是否是promise
然后在 onFulfilled(this.#result) 返回后 先去判断一下是否是promise

class MyPromise {
	// 省略上面
	// 判断是否是一个类promise
	// 判断不管你是一个对象还是一个方法,只要带有then方法,就可以互操作
	#isPromiseLike(result) {
		if (result !== null && (typeof result === 'object' || typeof result === 'function')) {
			if (typeof result.then === 'function') {
				return true
			}
		}
		return false
	}
	// 省略下面
	// 改造
	try {
		// 调用onFulfilled 会有返回值,需要重新reject出去
		const result = onRejected(this.#result);
		// Promise A+ 规范 说只要是 带有then方法 就 是类Proimise, 
		if (this.$isPromiseLike(result)){
			// 执行then方法
			data.then(resolve, reject)
		} else {
			reject(result ); // 这里不用变,还是reject
		}
	}
	
}
// 测试一下
setTimeout(() => {
	console.log('我应该是最后一个执行')
}, 0)
const p1 = new MyPromise((resolve) => {
	resolve('我是MyPromise')
}).then(res => {
	return new Promise((resolve) => {
		resolve('我是系统promise resolve的数据')
	})
}).then(res => {
	// 照道理这里应该打印    我是系统promise resolve的数据
	console.log(res )
})
const p2 = new MyPromise((resolve) => {
	resolve('我是MyPromise')
}).then(res => {
	const obj = {
		then: (resolve, reject) => {
			resolve('我是一个obj上的一个then方法')
		}
	}
	return obj
}).then(res => {
	// 照道理这里应该打印    我是一个obj上的一个then方法
	console.log(res )
})
console.log('我是同步代码,我应该最先被执行')

会发现最后一行的打印 console.log('我是同步代码,我应该最先被执行') 并没有被优先执行
原因是没有加入到微任务队列中去

2.9 加入微任务队列

定义joinToMicroTask

#joinToMicroTask(fn) {
	// 假如是node环境 判断 process
	if (typeof process === 'object' && typeof process.nextTick === 'function') {
		process.nextTick(fn)
	} else if (typeof MutationObserver === 'function') { // 判断是浏览器环境, 用 MutationObserver 实现
		// 注册一个观察器
		const observer = new MutationObserver(fn);
		// 定义一个文本节点, 初始值为1
		const textNode= document.createTextNode('1');
		// 观察文本节点的变化
		observer.observe(textNode, {
			characterData: true
		})
		textNode.data = '2'
	}
}

#handlerThenFn () {
	// 省略上面
	const { onFulfilled,
			onRejected,
			resolve,
			reject } = this.#currentThenParams.shift();
	}
	this.#joinToMicroTask(() => {
		if (typeof onFulfilled === 'function') {
		// 下面省略
	})
} 

2.10 实现catch方法

mdn 上描述catch方法
在这里插入图片描述
意思就是说就调用then方法

// 直接效用then方法即可
catch (onRejected) {
	return this.then(undefined, onRejected)
}
// 测试
	new MyPromise((resolve,reject) => {
		reuject(123123)
	}).catch ((err) => {
		console.log('catch被执行', err)
	})

2.11 实现finally方法

mdn 上描述finally方法
在这里插入图片描述
意思是说,直接调用then方法, 然后把onFinally 传进去,并且onFinally的回调函数 是没有参数 ,而且和原始promise状态一致,也就是直接把原始promise的数据返回即可

// 直接效用then方法即可
	// finally
	finally (onFinally) {
		return this.then((data) => {
			// 这里没有参数的
			onFinally();
			// 返回的状态与原始promise状态一致,直接把当前data返回
			return data;
		}, (error) => {
			onFinally();
			// 返回的状态与原始promise状态一致,抛个错, 这一步会被上面try catch 捕捉到
			throw error
		})
	}
	// 测试
	new MyPromise((resolve,reject) => {
		// resolve(123);
		reuject(123123)
	}).finally(() => {
		console.log('finally被执行')
	})

2.12 实现静态resolve 方法

mdn 上描述resolve方法
在这里插入图片描述

意思是,首先是一个静态方法,意味着是MyPromise.resolve 调用
如果resolve传入的是一个promise,那么直接返回传入的promise
如果是类Promise,那么就最后会返回一个promise,并且 执行传入的值上面的then方法
如果是字符串,number等其他数据,那就返回promise 返回传入的数据

	static resolve (data) {
		// 如果是我们自己写的Oromise, 直接返回即可
		if (data instanceof MyPromise) return data;
		// 由于静态方法里面无法获取实例方法, 那我们创建一个Promise
		let _resolve, _reject;
		const p = new MyPromise((resolve, reject) => {
			_resolve = resolve;
			_reject = reject;
		})
		// 此时p 就是一个实例
		if (p.#isPromiseLike(data)) {
			data.then(_resolve, _reject)
		} else {
			_resolve(data)
		}
		return p
	}
// 测试
const p = new Promise((resolve) => {
	resolve(123)
})
const p2 = new Promise((resolve) => {
	resolve(123)
})
const obj = {
	then((resolve, reject) => {
		resolve('obj')
	})
}
console.log(MyPromise.resolve(p).then(data => {console.log(data)}))
console.log(MyPromise.resolve(p2) === p2)
console.log(MyPromise.resolve(obj).then(data => {console.log(data)}))
console.log(MyPromise.resolve(12313123123).then(data => {console.log(data)}))

2.13 实现静态reject方法

mdn 上描述reject方法
在这里插入图片描述
意思是,不传传进来的是什么,我都返回一个拒绝的promse

	static reject (error) {
		return new MyPromise((resolve, reject) => {
			// 不传传进来什么,我都拒绝
			reject(error)
		})
	}

2.14 实现all方法

mdn 上描述all方法
在这里插入图片描述
意思是,接受一个可迭代对象,(可能是Set,Array等),返回一个promise。
当所有都返回成功,那就返回成功
只要有一个失败,那就返回失败的原因

	// 接受一个可迭代对象 
	static all (iteratorObj) {
		// 判断是否可迭代,不可迭代抛错
		if (!(iteratorObj != null && typeof iteratorObj[Symbol.iterator] === 'function')) {
			throw new TypeError(`${iteratorObj} is not iterable (cannot read property Symbol(Symbol.iterator))`)
		}

		// 首先需要一个Promise,并且最终会被返回
		let _resolve, _reject; // 先不管,先保存下来
		const p = new MyPromise((resolve, reject) => {
			_resolve = resolve;
			_reject = reject;
		})
		// 可迭代对象肯定能被for of 遍历,但拿不到下标,需要外部定义一个下标,在遍历的时候手动维护
		// promise的返回值只有执行完成后才能拿到,定义一个数组,用于保存成功的promise返回值
		let count = 0;
		let successCount = 0; // 成功的次数
		const successArr = [];
		for (const item of iteratorObj) {
			console.log(item);
			// 因为promise是异步的,不知道啥时候返回,不能使用count作为下标
			// 作用域种保存当前promise执行后需要塞到数组下标的那个位置
			const index = count;
			count++;
			// 先变成一个promise
			MyPromise.resolve(item).then(data => {
				// 把数据塞到保存的对应下标的位置
				successArr[index] = data;
				successCount++
				// 当所有的promise 全都完成的时候就节俗promise
				// 也就是成功的数组长度=== count, bindqie
				if (successCount === count) {
					_resolve(successArr)
				}
			}, error => {
				// 只要有一个失败了,那就借宿了
				_reject(error)
			})
		}
		// 如果传入的对象没有什么可以迭代 ,那就返回空数组
		if (count === 0) {
			_resolve([])
		}
		return p
	}
	// 测试
	const p1 = new Promise((resolve) => {
	  resolve(123)
	})
	const p2 = new MyPromise((resolve) => {
	  setTimeout(() => {
	    resolve(123)
	  }, 1000)
	})
	const p3 = new MyPromise((resolve, reject) => {
   		reject(123)
	})
	MyPromise.all([123, null, p1, p2, p3]).then(rs => {
	  console.log(rs)
	}).catch(err => console.log('有一个拒绝了', err))
	MyPromise.all(new Set([123, null, p1, p2])).then(rs => {
	  console.log(rs)
	})

其他方法 race,any,allSettled 原理差不多,这里不写了。
附上完整源码

const PENDING = 'pending';
const FULFILLED= 'fulfilled';
const REJECTED= 'rejected';


class MyPromise {
  // 私有属性外部不让用,用新出来的#前缀修饰
	//用 typescript 可以用 private
	// 默认是pedding状态
	#state = PENDING;

	// 定义结果,默认是undefined
	#result = undefined;

  // 保存当前then方法里面的方法地址
  #currentThenParams = [];

	// executor 是外部传入的
	constructor(executor) {
		// 解决 目录1.1 报错问题
		if (typeof executor !== 'function') {
			throw new TypeError(`Promise resolver ${executor} is not a function`)
		}
		// 外部会调用方法并传入参数,不传就是undefind
    const resolve= (data) => {
			this.#updateState(FULFILLED, data)
		}
		const reject= (error) => {
			this.#updateState(REJECTED, error)
		}
		/* 解决 内部报错问题 用try catch 包裹
    new Promise(() => {
				throw 123
			})
		*/
		// 注意:这里只能捕捉到同步错误,内部如果是setTimeout 返回的异步代码是捕捉不到的
		try {
			executor(resolve, reject)
		} catch (error) {
			// 报错 内部调用reject方法
			reject(error)
		}
	}

  // 传入状态和 结果// 统一入口,下面会用到
	#updateState (state, result) {
		if (this.#state !== PENDING) return;
		this.#state = state;
		this.#result = result;
    this.#handlerThenFn()
	}

	// 判断是否是一个类promise
	// 判断不管你是一个对象还是一个方法,只要带有then方法,就可以互操作
	#isPromiseLike(result) {
		if (result !== null && (typeof result === 'object' || typeof result === 'function')) {
			if (typeof result.then === 'function') {
				return true
			}
		}
		return false
	}

	#joinToMicroTask(fn) {
		// 假如是node环境 判断 process
		if (typeof process === 'object' && typeof process.nextTick === 'function') {
			process.nextTick(fn)
		} else if (typeof MutationObserver === 'function') { // 判断是浏览器环境, 用 MutationObserver 实现
			// 注册一个观察器
			const observer = new MutationObserver(fn);
			// 定义一个文本节点, 初始值为1
			const textNode= document.createTextNode('1');
			// 观察文本节点的变化
			observer.observe(textNode, {
				characterData: true
			})
			textNode.data = '2'
		} else {
			alert(1)
		}
	}

  #handlerThenFn () {
		// 当前状态没有变更就不执行
		if (this.#state === PENDING) return;
		while (this.#currentThenParams.length) {
			// 每次弹出一个去执行
			const { onFulfilled,
				onRejected,
				resolve,
				reject } = this.#currentThenParams.shift();
				
				this.#joinToMicroTask(() => {
					if (this.#state === FULFILLED) {
						// onFulfilled 可以是任意值,需要判断是否是函数
						if (typeof onFulfilled === 'function') {
							const result =  onFulfilled(this.#result);
							if (this.#isPromiseLike(result)) {
								result.then(resolve, reject)
							} else {
								resolve(result)
							}
						} else {
							// 走到这里说明传进来的是其他值,应该和resolve返回一致 的结果
							resolve(this.#result)
						}
					} else if (this.#state === REJECTED) {
						// onRejected可以是任意值,需要判断是否是函数
						if (typeof onRejected=== 'function') {
							const result = onRejected(this.#result)
							resolve(result)
						} else {
							// 走到这里说明传进来的是其他值,应该和resolve返回一致 的结果
							reject(this.#result)
						}
					}
			})
    }
  }

  // 有2个参数 onFulfilled 和 onRejected
	then (onFulfilled, onRejected) {
		// 返回一个新的promise,
		return new MyPromise((resolve, reject) => {
      // 把所有方法的地址存起来
      this.#currentThenParams.push({
        onFulfilled,
        onRejected,
        resolve,
        reject
      });
      this.#handlerThenFn()
		})
	}

	// 直接效用then方法即可
	catch (onRejected) {
		return this.then(undefined, onRejected)
	}

	// finally
	finally (onFinally) {
		return this.then((data) => {
			// 这里没有参数的
			onFinally();
			// 返回的状态与原始promise状态一致,直接把当前data返回
			return data;
		}, (error) => {
			onFinally();
			// 返回的状态与原始promise状态一致,抛个错, 这一步会被上面try catch 捕捉到
			throw error
		})
	}

	static resolve (data) {
		// 如果是我们自己写的Oromise, 直接返回即可
		if (data instanceof MyPromise) return data;
		// 由于静态方法里面无法获取实例方法, 那我们创建一个Promise
		let _resolve, _reject;
		const p = new MyPromise((resolve, reject) => {
			_resolve = resolve;
			_reject = reject;
		})
		// 此时p 就是一个实例
		if (p.#isPromiseLike(data)) {
			data.then(_resolve, _reject)
		} else {
			_resolve(data)
		}
		return p
	}

	static reject (error) {
		return new MyPromise((resolve, reject) => {
			// 不传传进来什么,我都拒绝
			reject(error)
		})
	}

	// 接受一个可迭代对象 
	static all (iteratorObj) {
		// 判断是否可迭代,不可迭代抛错
		if (!(iteratorObj != null && typeof iteratorObj[Symbol.iterator] === 'function')) {
			throw new TypeError(`${iteratorObj} is not iterable (cannot read property Symbol(Symbol.iterator))`)
		}

		// 首先需要一个Promise,并且最终会被返回
		let _resolve, _reject; // 先不管,先保存下来
		const p = new MyPromise((resolve, reject) => {
			_resolve = resolve;
			_reject = reject;
		})
		// 可迭代对象肯定能被for of 遍历,但拿不到下标,需要外部定义一个下标,在遍历的时候手动维护
		// promise的返回值只有执行完成后才能拿到,定义一个数组,用于保存成功的promise返回值
		let count = 0;
		let successCount = 0; // 成功的次数
		const successArr = [];
		for (const item of iteratorObj) {
			console.log(item);
			// 因为promise是异步的,不知道啥时候返回,不能使用count作为下标
			// 作用域种保存当前promise执行后需要塞到数组下标的那个位置
			const index = count;
			count++;
			// 先变成一个promise
			MyPromise.resolve(item).then(data => {
				// 把数据塞到保存的对应下标的位置
				successArr[index] = data;
				successCount++
				// 当所有的promise 全都完成的时候就节俗promise
				// 也就是成功的数组长度=== count, bindqie
				if (successCount === count) {
					_resolve(successArr)
				}
			}, error => {
				// 只要有一个失败了,那就借宿了
				_reject(error)
			})
		}
		// 如果传入的对象没有什么可以迭代 ,那就返回空数组
		if (count === 0) {
			_resolve([])
		}
		return p
	}

}

export default MyPromise
  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个简单的手写Promise实现: ```javascript class MyPromise { constructor(executor) { this.state = 'pending'; 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((callback) => callback(this.value)); } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach((callback) => callback(this.reason)); } }; 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; }; const promise2 = new MyPromise((resolve, reject) => { if (this.state === 'fulfilled') { setTimeout(() => { try { const x = onFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); } else if (this.state === 'rejected') { setTimeout(() => { try { const x = onRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); } else { this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const x = onFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const x = onRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }); } }); return promise2; } catch(onRejected) { return this.then(null, onRejected); } resolvePromise(promise2, x, resolve, reject) { if (promise2 === x) { reject(new TypeError('Chaining cycle detected')); } let called = false; if (x instanceof MyPromise) { x.then((value) => { this.resolvePromise(promise2, value, resolve, reject); }, (reason) => { if (!called) { called = true; reject(reason); } }); } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) { try { const then = x.then; if (typeof then === 'function') { then.call(x, (value) => { if (!called) { called = true; this.resolvePromise(promise2, value, resolve, reject); } }, (reason) => { if (!called) { called = true; reject(reason); } }); } else { resolve(x); } } catch (error) { if (!called) { called = true; reject(error); } } } else { resolve(x); } } static resolve(value) { return new MyPromise((resolve) => { resolve(value); }); } static reject(reason) { return new MyPromise((resolve, reject) => { reject(reason); }); } static all(promises) { const results = []; return new MyPromise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { const promise = promises[i]; if (!(promise instanceof MyPromise)) { promise = MyPromise.resolve(promise); } promise.then((value) => { results[i] = value; if (results.length === promises.length) { resolve(results); } }, (reason) => { reject(reason); }); } }); } static race(promises) { return new MyPromise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { const promise = promises[i]; if (!(promise instanceof MyPromise)) { promise = MyPromise.resolve(promise); } promise.then((value) => { resolve(value); }, (reason) => { reject(reason); }); } }); } } ``` 这个实现包含了Promise的基本功能,包括resolve、reject、then、catch、resolvePromise等方法,并且还实现Promise.all和Promise.race方法。但是这个实现并不完整,还有很多细节需要考虑和完善。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值