封装promise

94 阅读4分钟

前言

Promise介绍与基本使用

Promise 是一个 ECMAScript 6 提供的类,语法上Promise是一个构造函数,用来封装异步操作并可以获取成功和失败的结果。promise对象会有三种状态:pending初始状态、fulfilled成功状态、rejected失败状态。Promise对象有一下两个特点:1、对象的状态不受外界影响;2、一旦状态改变,就不会再改变了。

1、它可以绑定一个回调函数,避免回调函数作为参数传递。

2、链式调用,避免回调地狱。

实现

首先是promise的构造器函数。函数中会定义成功和失败的回调。即resolve和reject。

function Promise(executor) {
	// 类似于class的构造器,在 let p = new Promise() 的时候给 对象 p 初始化
	this.PromiseState = "pending";
	this.PromiseResult = null;

	// 声明属性。用于异步任务,此时p状态为pending,应该先保存onResolved,onReject方法,等异步任务执行完毕再调用对应方法 !!!!!!!!!!!!!!
	// 数组用于多次调用 p.then
	this.callback = []

	// 执行构造函数会将 this 指向 p 对象
	let that = this

	function resolve(data) {
		// p 的状态只能修改一次
		if (that.PromiseState !== "pending") return;
		// 如果写 this.PromiseState,则this为window,因为函数直接调用this指向 window
		that.PromiseState = "resolved"
		that.PromiseResult = data
		// 异步任务
		that.callback.forEach(item => {
			item.onResolved(data)
		})
	}

	function reject(data) {
		// p 的状态只能修改一次
		if (that.PromiseState !== "pending") return;
		that.PromiseState = "rejected"
		that.PromiseResult = data
		// 异步任务
		that.callback.forEach(item => {
			item.onReject(data)
		})
	}

	// new Promise 抛出异常,则修改状态为 rejected
	try {
		// new Promise后:1. 用executor 接收函数: (resolve,reject) => {resolve("ok")} 
		// 接收的函数也有方法,再传递方法
		executor(resolve, reject)
	} catch (e) {
		reject(e)
	}

}

接着在原型上定义 .then 回调

Promise.prototype.then = function(onResolved, onReject) {
	console.log("原型上的this指向p实例", this)
	const self = this
	// 异常穿透,以及判断回调函数参数。这样即使在 .then 中不传参数也能不中断执行。
	if (typeof onReject !== 'function') {
		onReject = reason => {
			throw reason;
		}
	}
	if (typeof onResolved !== 'function') {
		onResolved = value => value
	}

	// .then()返回一个promise对象
	return new Promise((resolve, reject) => {
		// 封装函数
		function callback1(type) {
			try {
				let result = type(self.PromiseResult)
				if (result instanceof Promise) {
					//  .then( value => prmise类型对象 ),则 返回值 由这个 promise类型对象决定(和其一样)。
					result.then(v => {
						resolve(v)
					}, r => {
						reject(r)
					})
				} else {
					//   .then( value => 非prmise类型对象 ),则 返回值为promise对象,
					//  状态为成功,值为返回值。

					resolve(result)
				}
			} catch (e) {
				//  .then( throw 异常 ),则 返回值 为失败 Promise 对象
				reject(e)
			}
		}

		if (this.PromiseState === "resolved") {
			callback1(onResolved)
		}
		if (this.PromiseState === "rejected") {
			callback1(onReject)
		}
		//异步任务
		if (this.PromiseState === "pending") {
			this.callback.push({
				onResolved: function() {
					// p 和 p.then 都是一个 promise对象,都有各自的 状态。这里是修改 p.then 状态
					callback1(onResolved)
				},
				onReject: function() {
					callback1(onReject)
				}
			})
		}
	})

}

异常捕获

Promise.prototype.catch = function(onReject) {
	return this.then(undefined, onReject)
}

完整代码

function Promise(executor) {
	// 类似于class的构造器,在 let p = new Promise() 的时候给 对象 p 初始化
	this.PromiseState = "pending";
	this.PromiseResult = null;

	// 声明属性。用于异步任务,此时p状态为pending,应该先保存onResolved,onReject方法,等异步任务执行完毕再调用对应方法 !!!!!!!!!!!!!!
	// 数组用于多次调用 p.then
	this.callback = []

	// 执行构造函数会将 this 指向 p 对象
	let that = this

	function resolve(data) {
		// p 的状态只能修改一次
		if (that.PromiseState !== "pending") return;
		// 如果写 this.PromiseState,则this为window,因为函数直接调用this指向 window
		that.PromiseState = "resolved"
		that.PromiseResult = data
		// 异步任务
		that.callback.forEach(item => {
			item.onResolved(data)
		})
	}

	function reject(data) {
		// p 的状态只能修改一次
		if (that.PromiseState !== "pending") return;
		that.PromiseState = "rejected"
		that.PromiseResult = data
		// 异步任务
		that.callback.forEach(item => {
			item.onReject(data)
		})
	}

	// new Promise 抛出异常,则修改状态为 rejected
	try {
		// new Promise后:1. 用executor 接收函数: (resolve,reject) => {resolve("ok")} 
		// 接收的函数也有方法,再传递方法
		executor(resolve, reject)
	} catch (e) {
		reject(e)
	}

}

Promise.prototype.then = function(onResolved, onReject) {
	console.log("原型上的this指向p实例", this)
	const self = this
	// 异常穿透,以及判断回调函数参数。这样即使在 .then 中不传参数也能不中断执行。
	if (typeof onReject !== 'function') {
		onReject = reason => {
			throw reason;
		}
	}
	if (typeof onResolved !== 'function') {
		onResolved = value => value
	}

	// .then()返回一个promise对象
	return new Promise((resolve, reject) => {
		// 封装函数
		function callback1(type) {
			try {
				let result = type(self.PromiseResult)
				if (result instanceof Promise) {
					//  .then( value => prmise类型对象 ),则 返回值 由这个 promise类型对象决定(和其一样)。
					result.then(v => {
						resolve(v)
					}, r => {
						reject(r)
					})
				} else {
					//   .then( value => 非prmise类型对象 ),则 返回值为promise对象,
					//  状态为成功,值为返回值。

					resolve(result)
				}
			} catch (e) {
				//  .then( throw 异常 ),则 返回值 为失败 Promise 对象
				reject(e)
			}
		}

		if (this.PromiseState === "resolved") {
			callback1(onResolved)
		}
		if (this.PromiseState === "rejected") {
			callback1(onReject)
		}
		//异步任务
		if (this.PromiseState === "pending") {
			this.callback.push({
				onResolved: function() {
					// p 和 p.then 都是一个 promise对象,都有各自的 状态。这里是修改 p.then 状态
					callback1(onResolved)
				},
				onReject: function() {
					callback1(onReject)
				}
			})
		}
	})

}

Promise.prototype.catch = function(onReject) {
	return this.then(undefined, onReject)
}

测试一下

首先,引入文件

	<script type="text/javascript" src="./js/promise.js"></script>
let p = new Promise((resolve, reject) => {
				setTimeout(() => {
					resolve("ok")
				}, 1000)
        })
			console.log("p", p)
			let res = p.then().then(value => {
				console.log(222)
			}).catch(reason => {
				console.warn(reason)
			})
			console.log("res", res)