Promise 源码记录(上课过程记录的笔记)
Promise.js代码:
仅仅实现了简单的then,catch和Promise对象的执行器函数
(function (window){ /** IIFE */
const PENDING ='pending';
const RESOLVED ='resolved';
const REJECTED = 'rejected';
function Promise(exector){
let self = this;
self.status = PENDING;
/**
* callbacks里面存储的数据类型为:{onResolved,onRejected}
*/
self.callbacks = [];
self.data = undefined;
function resolve(value){
if(self.status === PENDING){
self.data = value;
self.status = RESOLVED;
if(self.callbacks.length > 0){
self.callbacks.forEach(callbackObj => {
setTimeout(() => {
callbackObj.onResolved(value);
});
});
}
}
}
function reject(reasen){
if(self.status === PENDING){
self.data = reasen;
self.status = REJECTED;
if(self.callbacks.length > 0){
self.callbacks.forEach(callbackObj => {
setTimeout(() => {
callbackObj.onRejected(reason);
});
});
}
}
}
try{
exector(resolve,reject);
}catch(error){
reject(error);
}
}
/**
* 定义Promise的then方法实现回调
*/
Promise.prototype.then = function(onResolved, onRejected){
/**首先定义两个回调函数的形式
* 1. 如果两个回调时函数,则直接返回
* 2. 如果两个回调函数不是函数类型,强制其为函数
*/
onResolved = typeof onResolved === 'function' ? onResolved : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reasen => {throw reason};
const self = this;
return new Promise((resolve, reject) => {
/** 直接将RESOLVED/REJECTED状态下的执行器封装成一个函数 */
function handle(callback){
/** 这里要把执行函数放入异步队列中 */
/**
* 此处要定义Promise的状态,分为三种情况
* 1. 抛出异常,直接执行reject
* 2. 返回的值是Promise,则新的Promise的结果和状态由上一次的结果决定
* 3. 返回的值不是Promise,则新的Promise直接成功
*/
try {
const result = callback(self.data);
if(result instanceof Promise){
result.then(resolve, reject);
}else{
resolve(result);
}
} catch (reason) {
reject(reason);
}
}
/**
* 新的Promise的状态要根据onResolved/onRejected的执行结果来决定
*/
if(self.status === RESOLVED){
setTimeout(() => {
handle(onResolved);
});
}else if(self.status === REJECTED){
setTimeout(() => {
handle(onRejected);
});
}else{
/**
* 如果是PENDING状态,要把回调函数保存起来
* 但是不能直接去存,因为要根据之前的结果来定义新的Promise的状态
* 下面不需要异步调用,因为异步操作在Promise的执行器中已经做了
*/
self.callbacks.push({
onResolved(){
handle(onResolved);
},
onRejected(){
handle(onRejected);
}
});
}
});
}
/** 定义catch方法 */
Promise.prototype.catch = function(onRejected){
this.then(undefined, onRejected);
}
/** 向外暴露Promise */
window.Promise = Promise
})(window)
测试用的index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Promise</title>
<script src="./Promise.js"></script>
</head>
<body>
<script type="text/javascript">
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(5);
}, 3000);
});
p1.then(value => {
console.log("The anwser is successful, and the result is :", value);
return new Promise(() => {});
}).then(value => {
console.log("The next result is:", value);
}).catch(error => {
console.log("The error is :", error)
});
</script>
</body>
</html>