前言
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)