话不多说先贴上es6规范地址:ES6promise规范
先来看看promise的定义:
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
promise拥有以下特点:
- 只有一种状态,状态只能从pending --> fulfilled和 pending–> rejected;一旦状态改变就不会再变了
- 具有穿透作用,若是第二个then里面什么都没写,第三个then里面同样可接收数据
- then方法返回的是一个新的promise对象
具体实现步骤不多表述:看注释
class newPromise {
constructor(executor) {
// 初始化status为等待状态
this.status = 'pending';
this.value = undefined;
// 用来存储promise里面存在异步执行resolve和reject的情况下的回调,保证正常的输出结果
this.callbacks = []
let resolve = value => {
// state改变,resolve调用就会失败
if (this.status === 'pending') {
// resolve调用后,status转化为成功态
this.status = 'fulfilled';
// 储存成功的值
this.value = value;
// 异步执行回调
setTimeout(() => {
this.callbacks.map(callback => {
callback.onResolved(value)
})
});
}
};
let reject = reason => {
// state改变,reject调用就会失败
if (this.status === 'pending') {
this.status = 'rejected';
this.value = reason;
setTimeout(() => {
this.callbacks.map(callback => {
callback.onRejected(reason)
})
});
}
};
// 如果executor执行报错,直接执行reject
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onResolved, onRejected) {
const self = this
// 穿透加判断处理
if (typeof onResolved !== 'function') {
onResolved = v => v
}
if (typeof onRejected !== 'function') {
onRejected = r => { throw r }
}
return new newPromise((res, rej) => {
// 提取公共代码逻辑处理返回
// 存在几种情况:1、返回的就是新的promise对象,执行then方法就好
// 2、返回的是一个值,直接使用新promise改变状态函数
// 3、返回的事错误结果
function handle(callback) {
try {
let result = callback(self.value)
// 处理返回的是一个新的promise的情况
if (result instanceof newPromise) {
result.then(
v => v,
r => r
)
} else {
res(result)
}
} catch (error) {
rej(error)
}
}
if (this.status === 'pending') {
// console.log(this, 'this')
self.callbacks.push({
onResolved() {
// try {
// let result = onResolved(value)
// res(result)
// } catch (error) {
// let result = onRejected(error)
// rej(result)
// }
handle(onResolved)
},
onRejected() {
// try {
// let result = onRejected(reason)
// res(result)
// } catch (error) {
// let result = onRejected(error)
// rej(result)
// }
handle(onRejected)
}
})
}
if (this.status === 'fulfilled') {
setTimeout(() => {
handle(onResolved)
// let result = onResolved(this.value)
// res(result)
});
}
if (this.status === 'rejected') {
setTimeout(() => {
handle(onRejected)
// let result = onRejected(this.value)
// rej(result)
});
}
})
}
}