简单点来说就是异步,存在的意义在于将多级嵌套的异步调用(回调地狱)变为链式结构来处理,这篇博文主要说一个自己的简单实现思路。(有不对的请指正)
下面是一个简单的Promise实例
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2333)
}, 2000)
}).then(res => {
console.log(res)
})
function fn(resolve, reject) {}
Promise.prototype = function then(resCallback, errCallback){}
resolve(val)
或者reject(val)
中调用的参数valpending、fulfilled、rejected
,需要有一个变量_status
去储存状态(pending表示正在等待调用,fulfilled表示调用成功,rejected表示调用失败,主要为了在then方法中判断应该调用哪种回调函数)可以看出Promise的本质实际是个回调函数,下面一步一步来分析Promise的内部基本构造
// 构造函数
// fn : function fn(resolve, reject){ ...some code }
function _promise(fn) {
let _self = this;
this._value; // undefined 保存resolve(val)或者reject(val)中调用的参数val
this._status = "pending"; // 保存promise的状态
let _resolve = function(val) {
if(_self._status !== "pending") return; // promise的状态是单向的
_self._status = "fulfilled"; //调用_resolve表示操作成功
_self._value = val; // 保存val 方便在then中调用
}
let _reject = function(val) {
if(_self._status !== "pending") return; // promise的状态是单向的
_self._status = "rejected"; //调用_reject表示操作失败
_self._value = val;
}
fn(_resolve, _reject); //回调
}
_promise.prototype.then = function (onFulfilled, onRejected){
onFulfilled && onFulfilled(this._value);
onRejected && onRejected(this._value);
}
new _promise((resolve, reject) => {
resolve(2333);
}).then(res => {
console.log("这里是自定义_promise:", res);
})
基本思路上面的已经完成,但是还有两个大问题:
定义两个数组onResolvedCallback
和 onRejectedCallback
来存放所有then中的回调函数,在then中将回调函数保存在数组中,那在什么时候调用呢?仔细想想,其实onResolvedCallback
和 onRejectedCallback
是在_resolve/_reject
后调用的,于是思路清晰了,先在then
中定义一个回调函数,然后在_resolve/_reject
中进行调用。
function _promise(fn) {
let _self = this;
this._value;
this._status = "pending";
/-- 增加两个变量来存放then中的callback --/
this.onResolvedCallback = [];
this.onRejectedCallback = [];
let _resolve = function(val) {
if(_self._status !== "pending") return;
_self._status = "fulfilled";
_self._value = val;
/-- 在这里调用callback,不管后面的链式调用中有多少个then,这里都是按顺序执行 --/
for(let i=0; i<_self.onResolvedCallback.length; i++) {
_self.onResolvedCallback[i](val);
}
}
let _reject = function(val) {
if(_self._status !== "pending") return;
_self._status = "rejected";
_self._value = val;
/-- onRejectCallback同理 --/
for(let i=0; i<_self.onRejectedCallback.length; i++) {
_self.onRejectedCallback[i](val);
}
}
fn(_resolve, _reject);
}
_promise.prototype.then = function (onFulfilled, onRejected) {
//onFulfilled && onFulfilled(this._value);
//onRejected && onRejected(this._value);
/-- 这里不直接调用回调函数了,而是将回调函数保存在数组中 --/
this.onResolvedCallback.push(onFulfilled);
this.onRejectedCallback.push(onRejected);
}
let promise1 = new _promise((resolve, reject) => {
resolve("没有设置延迟的resolve");
}).then(res => {
console.log("这里是自定义_promise:", res); // 没有打印内容
})
let promise2 = new _promise((resolve, reject) => {
setTimeout(() => {
resolve("设置延迟了哦");
}, 2000)
}).then(res => {
console.log("这里是自定义_promise:", res); // 打印出 “这里是自定义_promise: 设置延迟了哦”
})
上面的思路有了,但是实际上代码运行是有问题的,,链式调用解决了,但是异步的问题没解决,大家想想上面的逻辑
then
中定义的函数保存在数组里_resolve
或_reject
运行结束后调用callback
callback
没有成功调用。promise2设置延迟,callback
成功调用callback
加入到数组中,然后再进行函数调用的,所以应该为_resolve
和_reject
添加setTimeout
。function _promise(fn) {
let _self = this;
this._value;
this._status = "pending";
this.onResolvedCallback = [];
this.onRejectedCallback = [];
let _resolve = function(val) {
/-- 保证then中的callback先定义再使用 --/
setTimeout(() => {
if(_self._status !== "pending") return;
_self._status = "fulfilled";
_self._value = val;
for(let i=0; i<_self.onResolvedCallback.length; i++) {
_self.onResolvedCallback[i](val);
}
})
}
let _reject = function(val) {
/-- 保证then中的callback先定义再使用 --/
setTimeout(() => {
if(_self._status !== "pending") return;
_self._status = "rejected";
_self._value = val;
for(let i=0; i<_self.onRejectedCallback.length; i++) {
_self.onRejectedCallback[i](val);
}
})
}
/-- 我相信你一定能看懂这里加入的try --/
try {
fn(_resolve, _reject);
} catch(err) {
_reject(err);
}
}
_promise.prototype.then = function (onFulfilled, onRejected) {
this.onResolvedCallback.push(onFulfilled);
this.onRejectedCallback.push(onRejected);
}
let promise1 = new _promise((resolve, reject) => {
resolve("没有设置延迟的resolve");
}).then(res => {
console.log("这里是自定义_promise:", res); // 打印出 “没有设置延迟的resolve”
})
let promise2 = new _promise((resolve, reject) => {
setTimeout(() => {
resolve("设置延迟了哦");
}, 2000)
}).then(res => {
console.log("这里是自定义_promise:", res); // 打印出 “这里是自定义_promise: 设置延迟了哦”
})
到这里一个基本功能已经完成,本瓜皮语死早,不知道上面的代码有没有表达清楚我的意思,如果看到这里可以理解我的意思,那么恭喜你Promise的基本原理你已经掌握了,下面可以对代码再进行一点优化。
个人认为是对Promise原理的理解中比较重要的一部分
先来观察一下Promise
中的then
方法,Promise
是为了解决回调地狱而存在的,假如现在有若干个异步任务,即:job1.then(job2).then(job3)…catch(handleError);
Promise
catch
方法)先贴一个Promise链式调用的例子
let multiply = function(input) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(input * input);
}, 500)
})
}
let add = function(input) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(input + input);
}, 500)
})
}
let p = new Promise((resolve, reject) => {
resolve(1);
})
p.then(multiply)
.then(add)
.then(res => {
console.log("结果是:", res);
})
then
方法返回的是一个Promise// ...省略一些代码
_promise.prototype.then = function(onFulfilled, onRejected) {
let _self = this;
return new Promise((resolve, reject) => {
_self.onResolvedCallback.push((val) => {
onFulFilled(val);
})
})
}
then
方法中return,要保证可以链式调用// ...省略一些代码
_promise.prototype.then = function(onFulfilled, onRejected) {
let _self = this;
return new _promise((resolve, reject) => {
_self.onResolvedCallback.push((val) => {
let x = onFulfilled(val); // 如果then中return,则x有值
resolve(x);
})
})
}
new _promise((resolve, reject) => {
resolve(123);
}).then(res => {
return res + 20;
}).then(res => {
console.log(res); // 输出: 143
return new _promise((resolve, reject) => {
resolve(res + 20);
})
}).then(res => {
console.log(res); // 输出:_promise{_status: 'fulfilled', onResolvedCallback: [], onRejectedCallback: [], _value: 163}
})
resolve
了,需要添加判定条件并进行处理resolve
或者reject
的参数x.then(resolve, reject)
,将外层_promise
的resolve
和reject
作为onFulfilled
和onRejected
传递到内层_promise
// ...省略一些代码
_promise.prototype.then = function(onFulfilled, onRejected) {
let _self = this;
return new _promise((resolve, reject) => {
_self.onResolvedCallback.push((val) => {
let x = onFulfilled(val);
// 判断x的类型
if(x instanceof _promise) {
x.then(resolve, reject);
} else {
resolve(x);
}
})
})
}
new _promise((resolve, reject) => {
resolve(123);
}).then(res => {
return res + 20;
}).then(res => {
console.log(res); // 输出: 143
return new _promise((resolve, reject) => {
resolve(res + 20);
})
}).then(res => {
console.log(res); // 输出163
})
这样_promise的链式调用也完成了,最后完善一下(做一下reject的处理),完整代码如下,下面代码只是一个Promise的基本原理的实现,实际的Promise还需要做一些代码健壮性处理(比如try catch),
还有一些Promise的方法,如:
_promise.ptorotype.catch()
_promise.ptorotype.finally()
_promise.all()
_promise.race()
感兴趣的可以自己尝试写一下,再阅读源码看看自己写的有哪些不足
function _promise(fn) {
let _self = this;
this._value;
this._status = "pending";
this.onResolvedCallback = [];
this.onRejectedCallback = [];
let _resolve = function(val) {
setTimeout(() => {
if(_self._status !== "pending") return;
_self._status = "fulfilled";
_self._value = val;
for(let i=0; i<_self.onResolvedCallback.length; i++) {
_self.onResolvedCallback[i](val);
}
})
}
let _reject = function(val) {
setTimeout(() => {
if(_self._status !== "pending") return;
_self._status = "rejected";
_self._value = val;
for(let i=0; i<_self.onRejectedCallback.length; i++) {
_self.onRejectedCallback[i](val);
}
})
}
try {
fn(_resolve, _reject);
} catch(err) {
_reject(err);
}
}
/**
@params function, function
@return _promise
**/
_promise.prototype.then = function(onFulfilled, onRejected) {
let _self = this;
return new _promise((resolve, reject) => {
_self.onResolvedCallback.push((val) => {
let x = onFulfilled(val);
// 判断x的类型
if(x instanceof _promise) {
x.then(resolve, reject);
} else {
resolve(x);
}
})
_self.onRejectedCallback.push((val) => {
let x = onRejected(val);
// 判断x的类型
if(x instanceof _promise) {
x.then(resolve, reject);
} else {
reject(x);
}
})
})
}
看了一些大佬的文章,一步一步解读最后写了这篇Promise基本原理的实现,有理解不对的地方希望大家指正!