知其然必知起所以然
Promise是用来处理异步的一种方案,以前如果在有碰到回调地狱的情况,代码看起来就非常的糟糕,有了promise之后,确实在整体上来说提上了不上,代码间接优美了很多。那么今天就来看一下promise是如何实现。
promise的基本结构
我们都知道promise有三种状态,pending, resolved, rejectd 这三种, 当pending的时候我们并不需要做什么,而resolved执行resolve函数,rejected 执行reject函数
所以可以描述出基本的结构
function Promisex(executor) {
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
// 当Promise对象已经由pending状态改变为了成功态(resolved)或是失败态(rejected)就不能再次更改状态了
var resolve = value => {
// 这个地方说明状态为pending才能更新
if (this.status === 'pending') {
this.status = 'resolved';
this.vaule = value
}
}
var reject = reason => {
if (this.status === 'pending') {
this.status = reject
this.reason = reason
}
};
executor(resolve, reject)
接着再来定义一下then的结构
Promisex.prototype.then = function(onFullFilled, onRejected) {
if (this.status === 'resolved') {
onFullFilled(this.value);
}
if (this.status === 'rejected') {
onRejected(this.reason);
}
}
上面可以很容易就展现了一个promise基本的形状
异步解决
你很可能发现上面的函数是同步的吗,如果你异步调用是不起作用的,那么如何解决异步方案--可以通过发布订阅者模式来进行
function Promisex() {
```` 省略
this.onFullFilledFunc = [] // 这里存放成功回调
this.onRejectedFunc = [] // 这里存放失败回调
}
Promisex.prototype.then = function (onFullFilled, onRejected) {
// 如果是异步的话,这个地方进来还是pending 状态
if (typeof onFullFilled === 'function') {
this.onFullFilledFunc.push(onFullFilled);
}
if (typeof onRejected === 'function') {
this.onRejectedFunc.push(onRejected);
}
}
这样就成功处理了promise的静态调用
链式调用
Promise链式调用的核心就把每个结果集再次包裹成一个Promise对象,然后循序调用
所以就可以来一个基本结果样貌
Promisex.prototye.then = function (onFullFilled, onRejected) {
var promisex1 = new Promsiex( (resolve, reject) => {
`````` 省略
})
return promisex1
}
如何实现链式调用呢?我们把这个过程抽象成一个函数,来分解
/**
* 解析then返回值与新Promise对象
* @param {Object} promise2 新的Promise对象
* @param {*} x 上一个then的返回值
* @param {Function} resolve promise2的resolve
* @param {Function} reject promise2的reject
*/
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
reject(new TypeError('Promise发生循环引用'));
}
if (x !== null && (typeof x === 'object' || x === 'function')) {
// 可能是个对象或者函数
try {
let then = x.then;
if (typeof then === 'function') {
then.call(
x,
y => {
// resolve(y)
//递归调用,传入y若是Promise对象,继续循环
resolvePromise(promise2, y, resolve, reject);
},
r => {
reject(r);
},
);
} else {
resolve(x);
}
} catch (e) {
reject(e);
}
} else {
resolve(x);
}
}
具体完整实现过程
function Promisex(executor) {
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFullFilledFunc = []; // 保存成功回调状态
this.onRejectedFunc = []; // 保存失败回调状态
// 当Promise对象已经由pending状态改变为了成功态(resolved)或是失败态(rejected)就不能再次更改状态了
var resolve = value => {
// 这个地方说明状态为pending才能更新
if (this.status === 'pending') {
this.value = value;
this.onFullFilledFunc.forEach(fun => {
this.value= fun(this.value);
});
this.status = 'resolved';
}
};
var reject = reason => {
if (this.status === 'pending') {
this.onRejectedFunc.forEach(fun => fun(reason));
this.reason = reason;
this.status = 'rejected'
}
};
executor(resolve, reject);
}
Promisex.prototype.then = function(onFullFilled, onRejected) {
if (this.status === 'pending') {
if (typeof onFullFilled === 'function') {
this.onFullFilledFunc.push(onFullFilled);
}
if (typeof onRejected === 'function') {
this.onRejectedFunc.push(onRejected);
}
return this;
}
var promise2 = new Promisex((resolve, reject) => {
if (this.status === 'resolved') {
setTimeout(() => {
try {
let x = onFullFilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === 'rejected') {
onRejected(this.reason);
}
});
return promise2;
};
/**
* 解析then返回值与新Promise对象
* @param {Object} promise2 新的Promise对象
* @param {*} x 上一个then的返回值
* @param {Function} resolve promise2的resolve
* @param {Function} reject promise2的reject
*/
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
reject(new TypeError('Promise发生循环引用'));
}
if (x !== null && (typeof x === 'object' || x === 'function')) {
// 可能是个对象或者函数
try {
let then = x.then;
if (typeof then === 'function') {
then.call(
x,
y => {
// resolve(y)
//递归调用,传入y若是Promise对象,继续循环
resolvePromise(promise2, y, resolve, reject);
},
r => {
reject(r);
},
);
} else {
resolve(x);
}
} catch (e) {
reject(e);
}
} else {
resolve(x);
}
}
module.exports = Promisex;
网友评论