(function(){
// 实现Promise
function _Promise(fn){
// 要求接收的fn必须是一个函数,否则报错
if(typeof fn !== 'function') {
throw new TypeError('_Promise resolver undefined is not a function')
}
// 每个实例应该有这两个属性:state,result
this.state = 'pending'; // 初始状态为 pending
this.result = undefined; // 初始结果为 undefined
// 事件池(自定义):这里存放的是then中传递的A函数和B函数
this.eventPool = {
A: function(){},
B: function(){}
}
// 立即执行传递进来的fn函数:但是在执行fn的时候得给fn床底两个函数 resolev,reject
var that = this;
function resolve(res){
// 这里接收一个参数,作为当前实例的result值
// 执行这个函数的时候会将当前实例的状态从 pending转为 resolved
/* if(that.state !== 'pending') return;
that.state = 'resolved';
that.result = res; */
change('resolved', res)
}
function reject(rej){
// 这里接收一个参数,作为当前实例的result值
// 执行这个函数的时候会将当前实例的状态从 pending转为 rejected
/* if(that.state !== 'pending') return;
that.state = 'rejected';
that.result = rej; */
change('rejected', rej)
}
// resolve函数和reject函数代码冗余,整合成一个
function change(state, result){
// 如果状态已经不是初始状态了,则直接退出,否则改变其状态和结果,并同时事件池中对应的函数执行
if(that.state !== 'pending') return;
that.state = state;
that.result = result;
// 通知事件执行是异步的
setTimeout(function(){
that.state === 'resolved'?
// 这里可以监控到执行then中的方法的返回结果
that.eventPool.A(that.result):
that.eventPool.B(result);
})
}
// 注意:执行fn的时候,如果有报错,则当前实例的状态为失败,值为失败的原因
try{
fn(resolve, reject);
}catch(err){
change('rejected', err);
}
}
// _Promise的原型上有一个then方法,该方法接收两个函数A和B,根据实例的状态自动识别执行A还是B
/* _Promise.prototype.then = function(A, B){
// this:当前_Promise的实例
// A/B:是调用then的时候传递的两个函数
// 如果参数不传递,则顺延
if(typeof A !== 'function') {
A = function(res){
return _Promise.resolve(res);
}
}
if(typeof B !== 'function') {
B = function(rej) {
return _Promise.reject(rej)
}
}
this.eventPool.A = A;
this.eventPool.B = B;
} */
// 给原型上扩展方法还可以这么写:注意补上constructor
_Promise.prototype = {
constructor: _Promise,
then: function(A, B){
// this:当前_Promise的实例
// A/B:是调用then的时候传递的两个函数
// 如果参数不传递,则顺延
if(typeof A !== 'function') {
A = function(res){
return _Promise.resolve(res);
}
}
if(typeof B !== 'function') {
B = function(rej) {
return _Promise.reject(rej)
}
}
/* this.eventPool.A = A;
this.eventPool.B = B; */
// 每次调用then方法都会返回一个新的实例
var that = this;
return new _Promise(function(resolve, reject){
// resolve/reject函数执行是决定新实例的状态:可以通知then方法中对应的方法执行
// 把传递进来的需要执行的A、B函数进行包装
that.eventPool.A = function(res){
// 进行监测:如果执行报错,返回的实例状态就为失败,值为失败的原因;否则就为成功,值为执行resolve是返回的结果
try{
var value = A(res);
// 如果执行then的A方法返回的是一个新的_Promise实例,则这个新实例的状态和值直接决定返回实例的状态和值
if(value instanceof _Promise){
value.then(resolve, reject)
}else{
resolve(value);
}
}catch(err) {
reject(err);
}
};
that.eventPool.B = function(rej){
try{
var value = B(rej);
if(value instanceof _Promise){
value.then(resolve, reject)
}else{
resolve(value);
}
}catch(err) {
reject(err);
}
}
})
},
catch: function(B){
// catch(B)方法等价于then(null, B)
this.then(null, B);
}
}
// 快速创建一个状态为成功的实例
_Promise.resolve = function(res) {
return new _Promise(function(resolve){
resolve(res)
});
};
// 快速创建一个状态为失败的案例
_Promise.reject = function(res) {
return new _Promise(function(undefined, reject){
reject(res)
});
};
_Promise.all = function(arr){
return new _Promise(function(resolve, reject){
var index = 0; // 计数用的
var result = [];
function success(){
// 如果所有值都是成功的,则通知resolve执行
if(index >= arr.length) {
resolve(result);
}
}
// 一次循环每一个实例
for(var i=0; i< arr.length; i++) {
// 基于闭包机制解决索引号不同步的问题
(function(i){
var item = arr[i];
// 如果传的值不是_Promise实例,则直接存储
if(!(item instanceof _Promise)){
result[i] = item;
index++;
success();
return;
}
item.then(function(res){
result[i] = res;
index++;
success();
}).catch(function(rej){
reject(rej)
})
})(i)
}
});
}
// 支持浏览器导入和CommonJS/ES6Module模块导入
if(typeof window !== 'undefined') {
window._Promise = _Promise;
}
if(typeof module === 'object' && typeof module.exports === 'object'){
module.exports = _Promise;
}
})();
let p1 = new _Promise(function(resolev,reject){
reject(300);
});
/* let p2 = p1.then(res=>{
},rej=>{
console.log(rej);
});
p2.then(res=>{
console.log(res); // undefined 因为p1.then(A,B)执行B函数的时候,没有任何返回值
}); */
/* let p2 = p1.then(res=>{},rej=>{
console.log(rej);
return _Promise.resolve('成功的实例');
// 这里返回了一个状态为成功,值为‘成功的实例’的_Promise实例,所以p2的状态跟实例和这个返回的新实例保持一致
});
p2.then(res=>{
console.log(res); // '成功的实例'
}); */
/* let p2 = p1.then(res=>{}, rej=>{
console.log(rej, a); // 这里执行报错,所以p2的状态为失败
});
p2.then(res=>{
console.log(res);
}, rej=>{
// 所以执行的是失败的函数,值为p1.then中执行函数报错的原因
console.log(rej);
}); */
let q = _Promise.all([10, _Promise.resolve(20), 'ss', _Promise.resolve(300), _Promise.reject(404)]);
console.log(q);
q.then(res=>{
console.log(res);
})
用原生实现自己的Promise
最新推荐文章于 2023-09-22 18:01:37 发布