1、Promise在javascript中的重要性不言而喻,但很多同学并不清楚内部的实现机理,我就我的理解与大家分享一下;
2、最简单的办法就是根据官方的Promise效果来实现相同的效果,我之前也看过网上的相关实现,全篇看到底就懵了,我想能不能出浅入深一步一步来;
3、好了,先实现一个最简单的,只实现then方法,能够根据resolve与reject取到相关结果,仅做功能实现,后续再完善
1、promise.js
/**
* Promise简单实现 v0.0.1
*
* Date:2020-09-24
*
* Author:yusian
*/
(function (window) {
/**
* Promise状态值
*/
const PROMISE_STATE = {
PENDING: 'pending',
FILFULLED: 'filfulled',
REJECTED: 'rejected'
}
/**
* 构造函数,生成一个Promise对象,参数为函数
* 传入的函数带有2个参数,分别为resolve与reject
* resolve为带有value值的成功回调
* reject为带有reason值的失败回调
* @param {Function} excutor 执行器函数
*/
function Promise(excutor) {
let self = this;
this.state = PROMISE_STATE.PENDING;
this.data = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
/**
* 成功回调
* @param {any} value 成功回调值
*/
function resolve(value) {
if (self.state !== PROMISE_STATE.PENDING) return;
self.state = PROMISE_STATE.FILFULLED;
self.data = value;
self.onResolvedCallbacks.forEach(function (callback) {
callback(value);
})
}
/**
* 失败回调
* @param {any} reason 失败回调值或Error
*/
function reject(reason) {
if (self.state !== PROMISE_STATE.PENDING) return;
self.state = PROMISE_STATE.REJECTED;
self.data = reason;
self.onRejectedCallbacks.forEach(function (callback) {
callback(reason);
})
}
/**
* 同步执行异步任务,如有异常及时抛出并结束任务,调用失败回调
*/
try {
excutor(resolve, reject);
} catch (error) {
reject(error);
}
}
/**
* Promise回调,异步任务执行结束后会执行该回调
* 该方法调用可以在异步执行结束前或结束后,不影响回调
* @param {Function} onResolve 成功回调
* @param {Function} onReject 失败回调
*/
Promise.prototype.then = function (onResolve, onReject) {
let self = this;
// 如果是pending状态,则暂时将回调加入到队列中等待执行
if (self.state === PROMISE_STATE.PENDING) {
self.onResolvedCallbacks.push(function () {
setTimeout(function () { onResolve(self.data); })
})
self.onRejectedCallbacks.push(function () {
setTimeout(function () { onReject(self.data); })
})
}
// 如果是filfulled状态,则执行传入的onResolve函数
else if (self.state === PROMISE_STATE.FILFULLED) {
setTimeout(function () { onResolve(self.data); });
}
// 如果是rejected状态,则执行传入的onReject函数
else if (self.state === PROMISE_STATE.REJECTED) {
setTimeout(function () { onReject(self.data); });
}
}
/**
* 全局访问
*/
window.Promise = Promise;
})(window)
2、index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise简单实现</title>
<script src="lib/promise.js"></script>
</head>
<body>
<script>
console.log(1);
let p = new Promise(function (resolve, reject) {
console.log(2);
resolve(2);
});
console.log(p);
p.then(function (value) {
console.log(4);
console.log('onResolve:', value);
}, function (reason) {
console.log(4);
console.log('onReject:', reason);
})
console.log(3);
</script>
</body>
</html>
控制台输出结果:
1
2
Promise {}
3
4
onResolve: 2
解释说明:
* 为什么需要Promise?传统的的异步任务需要在执行前传入回调函数来获取结果,这很不方便,也不灵活,比如能不能在我指定的时机回调?我要多点触发怎么办?
* Promise中的重点是将异步任务中的回调方法
与结果
分别在promise对象中保存,在 适当 的时机进行回调,这让任务的执行与结果的处理进行了分离;
* 当前只是实现了then方法,可以获取异步任务的resolve或reject回调,但还不支持链式调用,也没有实现catch方法;
* 相关说明已经注释中标明,对于理解Promise应该有所帮助。