观察原生promise用法,咱们能够发现,在new Promise时候传入了一个函数,这个函数在规范中的叫法是exector 执行器
看到这里,咱们先有一个大概思路,构建一个本身的Promise构造函数。
javascript
// 这里咱们建立了一个构造函数 参数就是执行器
function Promise(exector) {
}复制代码
好的,第一步完成, 重点来了,这个Promise内部到底干了什么呢 能够看到,原生的exector中传入了两个参数,第一个参数执行会让promise状态变为resolve, 也就是成功, 第二个执行会让函数变为reject状态,也就是失败java
而且这连个形参执行以后均可以传入参数,咱们继续完善代码 咱们将这两个形参的函数封装在构造函数内部数组
// 这里咱们建立了一个构造函数 参数就是执行器
function Promise(exector) {
// 这里咱们将value 成功时候的值 reason失败时候的值放入属性中
let self = this;
this.value = undefined;
this.reason = undefined;
// 成功执行
function resolve(value) {
self.value = value;
}
// 失败执行
function reject(reason) {
self.reason = reason;
}
exector(resolve, reject);
}复制代码
这里问题来了,咱们知道,promise的执行过程是不可逆的,resolve和rejeact之间也不能相互转化, 这里,咱们就须要加入一个状态,判断当前是否在pending过程,另外咱们的执行器可能直接报错,这里咱们也须要处理一下。
// 这里咱们建立了一个构造函数 参数就是执行器
function Promise(exector) {
// 这里咱们将value 成功时候的值 reason失败时候的值放入属性中
let self = this;
// 这里咱们加入一个状态标识
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
// 成功执行
function resolve(value) {
// 判断是否处于pending状态
if (self.status === 'pending') {
self.value = value;
// 这里咱们执行以后须要更改状态
self.status = 'resolved';
}
}
// 失败执行
function reject(reason) {
// 判断是否处于pending状态
if (self.status === 'pending') {
self.reason = reason;
// 这里咱们执行以后须要更改状态
self.status = 'rejected';
}
}
// 这里对异常进行处理
try {
exector(resolve, reject);
} catch(e) {
reject(e)
}
}复制代码
// 咱们将then方法添加到构造函数的原型上 参数分别为成功和失败的回调
Promise.prototype.then = function(onFulfilled, onRejected) {
// 获取下this
let self = this;
if (this.status === 'resolved') {
onFulfilled(self.value);
}
if (this.status === 'rejected') {
onRejected(self.reason);
}
}复制代码
ok,咱们如今能够本身运行试试
let promise = new Promise((resolve, reject) => {
resolve("haha");
})
promise.then(data => {
console.log(data); //输出 haha
}, err=> {
console.log(err);
})
// 屡次调用
promise.then(data => {
console.log(data); //输出 haha
}, err=> {
console.log(err);
})复制代码
上面能够注意到, new Promise中的改变状态操做咱们使用的是同步,那若是是异步呢,咱们平时遇到的基本都是异步操做,该如何解决?promise
这里咱们须要在构造函数中存放两个数组,分别保存成功回调和失败的回调
由于能够then屡次,因此须要将这些函数放在数组中
代码以下:bash
// 这里咱们建立了一个构造函数 参数就是执行器
function Promise(exector) {
// 这里咱们将value 成功时候的值 reason失败时候的值放入属性中
let self = this;
// 这里咱们加入一个状态标识
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
// 存储then中成功的回调函数
this.onResolvedCallbacks = [];
// 存储then中失败的回调函数
this.onRejectedCallbacks = [];
// 成功执行
function resolve(value) {
// 判断是否处于pending状态
if (self.status === 'pending') {
self.value = value;
// 这里咱们执行以后须要更改状态
self.status = 'resolved';
// 成功以后遍历then中成功的全部回调函数
self.onResolvedCallbacks.forEach(fn => fn());
}
}
// 失败执行
function reject(reason) {
// 判断是否处于pending状态
if (self.status === 'pending') {
self.reason = reason;
// 这里咱们执行以后须要更改状态
self.status = 'rejected';
// 成功以后遍历then中失败的全部回调函数
self.onRejectedCallbacks.forEach(fn => fn());
}
}
// 这里对异常进行处理
try {
exector(resolve, reject);
} catch(e) {
reject(e)
}
}
// then 改造
Promise.prototype.then = function(onFulfilled, onRejected) {
// 获取下this
let self = this;
if (this.status === 'resolved') {
onFulfulled(self.value);
}
if (this.status === 'rejected') {
onRejected(self.reason);
}
// 若是异步执行则位pending状态
if(this.status === 'pending') {
// 保存回调函数
this.onResolvedCallbacks.push(() => {
onFulfilled(self.value);
})
this.onRejectedCallbacks.push(() => {
onRejected(self.reason)
});
}
}
// 这里咱们能够再次实验
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
if(Math.random() > 0.5) {
resolve('成功');
} else {
reject('失败');
}
})
})
promise.then((data) => {
console.log('success' + data);
}, (err) => {
console.log('err' + err);
})
复制代码
咱们都熟悉Jquery,它的链式调用是用rerun this来作的,但是这里却不行,缘由文章末尾再解释。 咱们采起返回一个新的promise对象来实现链式调用. 意思也就是p.then()返回一个新promise对象。dom
//给这个函数加个返回值,返回值就是一个新new的promise对象
Promise.prototype.then = function (onFulFilled, onRejected) {
let p2 = new Promise((resolve, reject) => {});
if (this.status === 'pending') {
this.onFulFilledCallbacks.push(() => {
onFulFilled(this.value)
});
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
} else if (this.status === 'resolved') {
onFulFilled(this.value);
} else if (this.status === 'rejected') {
onRejected(this.reason);
}
return p2;
}
复制代码