一、自定义Promise
Promise.js文件
/**
* 自定义Promise函数模块: ES5如何自定义模块?IIFE 匿名函数自调用;函数自调用
*/
(function(window) {
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";
/**
* Promise 构造函数 ;excutor 执行器函数 (同步执行);
*/
function Promise(excutor) {
// 将当前promise对象保存起来;
const self = this;
self.status = PENDING; // 给promsie指定status,初始为pendding;
self.data = undefined; // 给promise指定一个存储数据的属性
self.callbacks = []; // 每个元素的结构:{onResolved(){},onRejected(){}}
/** 用于改变promise状态 */
function resolve(value) {
// 如果当前状态不是pending,直接结束;因为 状态只能改变一次,status为pending的时候,才能继续往下执行;
if (self.status !== PENDING) return;
// 1. status状态改为resolved
self.status = RESOLVED;
// 2. 保存value数据
self.data = value;
// 如果有待执行的callback函数,立即异步执行(需放入队列中,这里借助setTimeout)回调函数onResolved;
if (self.callbacks.length > 0) {
setTimeout(() => {
// 放入队列中,执行所有成功的回调
self.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value);
});
});
}
}
function reject(reason) {
// 如果当前状态不是pending,直接结束;因为 状态只能改变一次,status为pending的时候,才能继续往下执行;
if (self.status !== PENDING) return;
// 1. status状态改为rejected
self.status = REJECTED;
// 2. 保存value数据
self.data = reason;
// 如果有待执行的callback函数,立即异步执行(需放入队列中,这里借助setTimeout)回调函数onResolved;
if (self.callbacks.length > 0) {
setTimeout(() => {
// 放入队列中,执行所有成功的回调
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason);
});
});
}
}
// 立即同步执行excutor
try {
excutor(resolve, reject);
} catch (error) {
reject(error); // 如果执行器抛出异常,promise变为失败状态,故调用reject
}
}
/**
* Promise原型对象的方法then();
* 指定成功或者失败的回调
* 返回一个promise对象
*/
Promise.prototype.then = function(onResolved, onRejected) {
const self = this;
// 指定回调函数的默认值,调用.then的时候,可能不执行onRejected
onResolved = typeof onResolved === "function" ? onResolved : value => value; // 向后传递成功的value
onRejected =
typeof onRejected === "function"
? onRejected
: reason => {
throw reason; // 指定默认的失败的回调,将异常传下去;(实现错误/异常传透);向后传递失败的reason
};
// 返回一个新的promise
return new Promise((resolve, reject) => {
function handler(callback) {
// 根据执行的结果,改变return的promise状态;
/**
* onResolved或者onRejected 的结果有三种情况:
* 1.抛出异常,return的promise就会失败,状态为rejected状态,reason就是error
* 2.返回一个非promise,return的promise就会成功,状态为resolved状态,value就是返回的值;
* 3.返回一个promise,return的promise的结果就是该promise的结果;
*/
try {
const result = callback(self.data);
if (result instanceof Promise) {
// result.then(
// value => {
// resolve(value);
// },
// reason => {
// reject(reason);
// }
// );
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
if (self.status === PENDING) {
// pending,将回调函数存起来,等待被执行;并让它影响return的promise的状态;
self.callbacks.push({
onResolved(value) {
// value,这个参数要不要都可
handler(onResolved);
},
onRejected(reason) {
handler(onRejected);
}
});
} else if (self.status === RESOLVED) {
// resolved,异步执行onResolved函数,并改变return的promise状态;
setTimeout(() => {
handler(onResolved);
});
} else {
// rejected,异步执行onRejected函数
setTimeout(() => {
handler(onRejected);
});
}
});
};
/**
* Promise 原型对象的catch()方法;
* 指定失败的回调;
* 返回一个promise
*/
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected);
};
// Promise原型链上的方法finally(onFinally) ;无论promise是fulfilled或者是rejected,都会执行指定的回调函数onFinally
/**
*本质上是有个then方法;且finally要在要在promise状态改变之后才执行
* 返回promise,返回的promsie的成功与否,取决于onFinally的结果;
* 而onFinally的执行结果,应该取决于前一个p 或者.then的执行结果;
* 这里有个很重要的点,finally表示的是一定会执行,但并不一定是最后执行;
* 所以在finally中,应该将p的value或者reason向后传递下去;
*/
Promise.prototype.finally = function(onFinally) {
onFinally = typeof onFinally === "function" ? onFinally : function() {};
return this.then(
value => {
return Promise.resolve(onFinally()).then(() => value); // 向后传递成功的value (调用finally的promsie的成功的value)
},
reason => {
return Promise.resolve(onFinally()).then(() => {
// 实现异常传透;向后传递失败的reason
throw reason;
});
}
);
};
/**
* Promise 函数对象的resolve方法;
* 返回一个成功或者失败的promise
*/
Promise.resolve = function(data) {
/**
* 1. 如果接收的是一般值,promise成功,value就是这个值;
* 2. 如果结束皮的是成功的promise,则promise成功,value是该promise的value;
* 3. 如果接收的是一个失败的promsie,则promsie失败,reason是该promsie的reason
*/
return new Promise((resolve, reject) => {
if (data instanceof Promise) {
data.then(resolve, reject);
} else {
resolve(data);
}
});
};
/**
* Promise 函数对象的reject方法;
* 返回指定结果的一个失败的promise;
*/
Promise.reject = function(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
};
/**
* Promise 函数对象的all(promises)方法;promises数组中的元素并不一定都是promsie,也可能只是一个普通的值,如:5
* 返回一个promise,当所有的promise都成功的时候,该promise 才是成功状态;如果成功,返回所有成功的promise;如果失败,返回失败的reason;
*/
Promise.all = function(promises) {
return new Promise((resolve, reject) => {
const values = new Array(promises.length); // 创建一个和promises长度相同的values数组;用于保存成功的value 数据;
let count = 0; // 用来保存成功的promsie的个数
// 遍历promises获取每个promise的结果
promises.forEach((p, index) => {
// 这里将的p不一定是一个promsie,故需将其包装成一个promsie;如果它是一个promsie,再包一层也无所谓; Promise.resolve(p)
Promise.resolve(p).then(
value => {
count++;
// 把value按顺序放入values中;;将value放入values中,且这里存的顺序应和传入的promsies中的顺序一致;(数组中的元素和传入all方法中的promsies中的顺序是一样的)
values[index] = value;
// 所有的成功了,将return的promise改为成功;
if (promises.length === count) {
resolve(values);
}
},
reason => {
reject(reason);
}
);
});
});
};
/**
* Promise函数对象的race方法;
* 返回一个promise,返回最先完成的那个promise,无论他成功还是失败;
*/
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
// 遍历promises获取每个promise的结果;因为promise的状态只能改变一次,故,只有第一次调用才有效果;
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
// 一旦有成功,就将return变为成功;
resolve(value);
},
reason => {
// 一旦失败,将return 变为失败
reject(reason);
}
);
});
});
};
/**
* Promise 函数对象的any(promises)方法;
* 返回第一个成功状态的promise;如果都失败,返回 AggregateError: All promises were rejected
*/
Promise.any = function(promises) {
return new Promise((resolve, reject) => {
let count = 0; // 记录失败的promsie个数
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
resolve(value);
},
reason => {
count++;
if (count === promises.length) {
reject("AggregateError: All promises were rejected");
}
}
);
});
});
};
/**
* Promsie 函数对象的allSettled(promises)方法;
* 返回一个promise,当所有的promise都是已敲定状态的时候,返回一个promise,并带有一个对象数组,
* 该对象数组是所有settled的promise的信息;
* 否则无返回;
*/
Promise.allSettled = function(promises) {
return new Promise((resolve, reject) => {
const values = new Array(promises.length); // 装所有settled的promsie
let count = 0; // 定义已经settled的promsie的个数
promises.forEach((p, index) => {
Promise.resolve(p)
.then(
value => {
values[index] = {
status: "fulfilled",
value: value
};
},
reason => {
values[index] = {
status: "rejected",
reason: reason
};
}
)
.then(value => {
// promise是settled状态的时候,才会进入这个then
count++;
if (count === promises.length) {
resolve(values);
}
});
});
});
};
// 自定义两个函数:resolveDelay和rejectDelay;
/**
* 返回一个promise对象,在指定时间过后,才确定promise结果
*/
Promise.resolveDelay = function(value, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (value instanceof Promise) {
value.then(resolve, reject);
} else {
resolve(value);
}
}, time);
});
};
// 返回一个promise对象,在指定时间过后,才失败
Promise.rejectDelay = function(reason, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(reason);
}, time);
});
};
// 向外暴露Promise函数
window.Promise = Promise;
})(window);
二、引入刚刚的Promise.js进行测试
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Promise</title>
</head>
<body>
<h1>test</h1>
<!-- 引入自定义的Promise.js文件 -->
<script src="./lib/Promise.js"></script>
<script>
const p1 = Promise.resolve(1);
const p2 = Promise.reject(2);
const pAll = Promise.all([p1, p2, 999]);
pAll
.then(value => {
console.log("value:", value);
})
.catch(reason => {
console.log("reason:", reason);
});
// 以上代码的打印结果:reason: 2
</script>
</body>
</html>