JS学习(三) 手写Promise

本文详细介绍了如何从零开始实现Promise,包括其构造函数、resolve和reject方法、then方法的处理逻辑,以及状态转换规则。同时,还涉及到错误处理、链式调用和静态方法如Promise.all和Promise.race的实现。
摘要由CSDN通过智能技术生成

好,我们今天来手写Promise
在这里插入图片描述

/*
 1.Promise 是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
 2.Promise 有三种状态 分别为 成功(fulfilled) 失败(rejected) 等待(pending)
 	pending -> fulfilled
 	pending -> rejected
 	一旦状态确定就不可更改
 3.resolve 跟 reject 就是用来更改状态的,resolve 就是把状态改为 fulfilled,reject就是把状态
 	改为 rejected
 4.then 方法内部做的事情就是判断状态,如果状态时成功,调用成功回调函数,如果状态时失败,调用失败回调函数.then 方法是被定义在原型对象中的
 5.then 成功回调函数有一个参数,表示成功之后的值,then 失败回调也有一个参数,表示失败的原因
 6. 同一个promise对象下面的then方法是可以被调用多次的
 7. then方法是可以被链式调用的, 后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
*/
let promise = new Promise((resolve,reject) => {
	resolve('成功')
	reject('失败')
})
promise.then(value => {}, reason => {})
//开搞开搞
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
	constructor (executor) {
	//捕获执行器中的错误
		try{
			executor(this.resolve,this.reject)
		}catch(e){
			this.reject(e)
		}
	}
	status = PENDING
	value = undefined
	reason = undefined
	// 成功回调,同一个promise对象的then方法可以多次调用,所以在异步的情况下,要用数组来存储成功回调或者失败回调
	successCallback = []
	// 失败回调
	failCallback = []
	// 定义 resolve 跟 reject
	// 因为以后调用 resolve 或者 reject 是直接调用的,如果用普通函数的写法的话,这个函数的 this 会指向 window 或者 undefined,所以要用箭头函数来让 this 指向 MyPromise 的实例对象
	resolve = value => {
		//如果状态不是 pending,阻止程序向下执行
		if(this.status !== PENDING) return
		//将状态更改为成功
		this.status = FULFILLED
		//保存成功之后的值
		this.value = value
		//判断成功回调是否存在,如果存在就调用
		//this.successCallback && this.successCallback()
		while(this.successCallback.length) {
			this.successCallback.shift()()
		}
	}
	reject = reason => {
		//如果状态不是 pending,阻止程序向下执行
		if(this.status !== PENDING) return
		//将状态更改为失败
		this.status = REJECTED
		//保存失败的原因
		this.reason = reason
		//判断失败回调是否存在,如果存在就调用
		//this.failCallback && this.failCallback(this.reason)
		while(this.failCallback.length) {
			this.failCallback.shift()()
		}
	}
	then (successCallback,failCallback) {
		//判断 then 是否有参数
		successCallback = successCallback ? successCallback : value => value
		failCallback = failCallback ? failCallback : reason => {throw reason}
		let promise2 = new MyPromise((resolve, reject) =>{
			//判断状态
			if (this.status === FULFILLED) {
				setTimeout(() => {
				//捕获成功回调的错误
					try{
						let suc = successCallback(this.value)
						//判断 suc 的值是普通值还是 promise 对象
						//如果是普通值,直接调用 resolve
						//如果是 promise 对象,查看 promise 对象返回的结果
						//再根据 promise 对象返回的结果,决定调用 resolve 还是调用 reject
						resolvePromise(promise2, suc, resolve, reject)
					}catch(e){
						reject(e)
					}
				})
			}else if(this.status === REJECTED) {
				setTimeout(() => {
				//捕获失败回调的错误
					try{
						let fail = failCallback(this.reason)
						//判断 fail 的值是普通值还是 promise 对象
						//如果是普通值,直接调用 resolve
						//如果是 promise 对象,查看 promise 对象返回的结果
						//再根据 promise 对象返回的结果,决定调用 resolve 还是调用 reject
						resolvePromise(promise2, fail, resolve, reject)
					}catch(e){
						reject(e)
					}
				})
			}else {//等待状态,此为在执行 MyPromise 时异步调用了resolve,所以才会有等待状态
				this.successCallback.push(() => {
					setTimeout(() => {
					//捕获成功回调的错误
						try{
							let suc = successCallback(this.value)
							//判断 suc 的值是普通值还是 promise 对象
							//如果是普通值,直接调用 resolve
							//如果是 promise 对象,查看 promise 对象返回的结果
							//再根据 promise 对象返回的结果,决定调用 resolve 还是调用 reject
							resolvePromise(promise2, suc, resolve, reject)
						}catch(e){
							reject(e)
						}
					})
				})
				this.failCallback.push(()=>{
					setTimeout(() => {
					//捕获失败回调的错误
						try{
							let fail = failCallback(this.reason)
							//判断 fail 的值是普通值还是 promise 对象
							//如果是普通值,直接调用 resolve
							//如果是 promise 对象,查看 promise 对象返回的结果
							//再根据 promise 对象返回的结果,决定调用 resolve 还是调用 reject
							resolvePromise(promise2, fail, resolve, reject)
						}catch(e){
							reject(e)
						}
					})
				})
			}
		})
		return promise2
	}
	finally (callback) {
		return this.then((value) => {
			return MyPromise.resolve(callback()).then(() => value)
		}, (reason) =>{
			return MyPromise.resolve(callback()).then(() => {throw reason})
		})
	}
	catch (failCallback) {
		return this.then(undefined, failCallback)
	}
	static all (array) {
		let result = []
		let index = 0
		return new MyPromise((resolve, reject) => {
			function addData (key, value) {
				result[key] = value
				// 考虑到异步的情况,所以要用计数器来保证数组里所有的Promise执行完成了再调用resolve
				index++
				if (index === array.length) {
					resolve(result)
				}
			}
			for(let i = 0; i < array.length; i++) {
				let current = array[i]
				if(current instanceof MyPromise){
					// MyPromise 对象
					current.then(value => addData(i, value), reason => reject(reason))
				}else {
					//普通值
					addData(i, array[i])
				}
			}
		})
	}
	static race (array) {
		return new MyPromise((resolve, reject) => {
			array.forEach(item => {
				if(item instanceof MyPromise){
					item.then(value => resolve(value), reason => reject(reason))
				}else {
					resolve(item)
				}
			})
		})
	}
	static resolve (value) {
		if (value instanceof MyPromise) {
			return value
		}else {
			return new MyPromise(resolve => resolve(value))
		}
	}
}
function resolvePromise(promise2, value, resolve, reject) {
	//判断是否promise对象自返回
	if(promise2 === x) {
		return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
	}
	if (value instanceof MyPromise) {
		value.then(resolve, reject)
	} else {
		resolve(value)
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当你需要手写一个 Promise 的时候,你可以按照以下步骤进行: 1. 创建 Promise 构造函数,并传入一个执行器函数作为参数: ```javascript function MyPromise(executor) { // TODO: 实现 Promise 的状态和值的存储 } ``` 2. 在构造函数中创建状态和值的存储变量,并初始化为初始状态: ```javascript function MyPromise(executor) { this.state = 'pending'; this.value = undefined; // TODO: 实现其他必要的变量和逻辑 } ``` 3. 定义 resolve 和 reject 函数,用于在异步操作完成时改变 Promise 的状态和值,并添加对应的回调函数: ```javascript function MyPromise(executor) { this.state = 'pending'; this.value = undefined; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; // TODO: 触发所有注册的成功回调函数 } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.value = reason; // TODO: 触发所有注册的失败回调函数 } }; // TODO: 调用执行器函数,并传入 resolve 和 reject 函数 } ``` 4. 在构造函数中调用执行器函数,并传入 resolve 和 reject 函数: ```javascript function MyPromise(executor) { this.state = 'pending'; this.value = undefined; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; // TODO: 触发所有注册的成功回调函数 } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.value = reason; // TODO: 触发所有注册的失败回调函数 } }; try { executor(resolve, reject); } catch (error) { reject(error); } } ``` 5. 添加 then 方法,用于注册成功回调函数和失败回调函数,并返回一个新的 Promise 对象: ```javascript function MyPromise(executor) { this.state = 'pending'; this.value = undefined; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; // TODO: 触发所有注册的成功回调函数 } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.value = reason; // TODO: 触发所有注册的失败回调函数 } }; try { executor(resolve, reject); } catch (error) { reject(error); } } MyPromise.prototype.then = function(onFulfilled, onRejected) { // 创建新的 Promise 对象 const newPromise = new MyPromise((resolve, reject) => { // TODO: 根据当前 Promise 的状态和值执行对应的回调函数,并处理返回值 }); // 返回新的 Promise 对象 return newPromise; }; ``` 6. 在成功回调函数和失败回调函数中处理返回值,并根据返回值的类型决定新 Promise 对象的状态和值: ```javascript function MyPromise(executor) { this.state = 'pending'; this.value = undefined; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; // TODO: 触发所有注册的成功回调函数 } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.value = reason; // TODO: 触发所有注册的失败回调函数 } }; try { executor(resolve, reject); } catch (error) { reject(error); } } MyPromise.prototype.then = function(onFulfilled, onRejected) { const newPromise = new MyPromise((resolve, reject) => { if (this.state === 'fulfilled') { // 如果当前 Promise 已经是 fulfilled 状态,则异步执行成功回调函数 setTimeout(() => { try { const result = onFulfilled(this.value); // 处理返回值,并根据返回值的类型决定新 Promise 对象的状态和值 handlePromiseResult(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); } else if (this.state === 'rejected') { // 如果当前 Promise 已经是 rejected 状态,则异步执行失败回调函数 setTimeout(() => { try { const result = onRejected(this.value); // 处理返回值,并根据返回值的类型决定新 Promise 对象的状态和值 handlePromiseResult(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); } else { // 如果当前 Promise 还是 pending 状态,则将回调函数添加到对应的队列中,等待执行 this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const result = onFulfilled(this.value); handlePromiseResult(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const result = onRejected(this.value); handlePromiseResult(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); }); } }); return newPromise; }; function handlePromiseResult(promise, result, resolve, reject) { if (promise === result) { // 如果返回的是当前 Promise 对象本身,则抛出 TypeError reject(new TypeError('Chaining cycle detected for promise')); } else if (result instanceof MyPromise) { // 如果返回的是一个 Promise 对象,则根据其状态和值决定新 Promise 对象的状态和值 if (result.state === 'fulfilled') { resolve(result.value); } else if (result.state === 'rejected') { reject(result.value); } else { // 如果返回的 Promise 对象还是 pending 状态,则等待其状态改变后再决定新 Promise 对象的状态和值 result.then(resolve, reject); } } else if (result && (typeof result === 'object' || typeof result === 'function')) { // 如果返回的是一个对象或函数,则尝试获取 then 方法 let then; try { then = result.then; } catch (error) { reject(error); } if (typeof then === 'function') { // 如果返回值有 then 方法,则将其视为 Promise-like 对象,并调用 then 方法 const promiseLikeObj = new MyPromise(then.bind(result)); promiseLikeObj.then(resolve, reject); } else { // 如果返回值没有 then 方法,则将其视为普通值,并将其作为新 Promise 对象的值 resolve(result); } } else { // 如果返回的是一个普通值,则将其作为新 Promise 对象的值 resolve(result); } } ``` 以上是一个简单的手写 Promise 的实现,仅供参考。实际上,原生的 Promise 还包含了更多的特性和细节,比如处理异步操作、链式调用、错误处理等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值