封装promise

85 阅读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)