实现内容:
1、then方法:当resolve时会触发then方法
2、catch方法:当reject时会触发catch方法
3、promise.resolve():直接生成一个成功状态的promise对象
4、promise.reject():直接生成一个失败状态的promise对象
5、Promise.all():参数为promise对象数组,等待所有状态都不为pending
6、Promise.race():参数为promise对象数组,运行最快的那一个触发then或catch
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>手写实现一个Promise</title>
</head>
<body>
</body>
<script type="text/javascript">
function MyPromise(fn) {
this.promiseState = 'pending';
this.promiseResult = undefined;
// 注册promise对象的任务函数
this.thenCallback = undefined;
this.catchCallback = undefined;
// 为保证this指向,使用变量进行保存
var _this = this;
var resolve = function(resolveVal) {
// 防止状态变更后,再次修改状态,promise状态一旦变更是不能回退的
if (_this.promiseState === 'pending') {
// 变更状态和值
_this.promiseState = 'fulfilled';
_this.promiseResult = resolveVal;
// 用setTimeout模拟异步
// 虽然resolve在then之前执行的
// 但是该函数的回调一定是在Promise对象初始化完毕后执行的
// 所以我们的回调执行时,thenCallback就已经初始化完毕了
if (resolveVal instanceof MyPromise) {
// dang传入的resolveVal是一个promise对象时,就可以直接用then去进行处理
resolveVal.then(function(res) {
if (_this.thenCallback) {
// 此时调用then中注册的回调函数时,应该传入该对象then之后的结果
_this.thenCallback(res);
}
})
} else {
setTimeout(function() {
if (_this.thenCallback) {
_this.thenCallback(resolveVal);
}
});
}
}
};
var reject = function(rejectVal) {
// 防止状态变更后,再次修改状态,promise状态一旦变更是不能回退的
if (_this.promiseState === 'pending') {
// 变更状态和值
_this.promiseState = 'rejected';
_this.promiseResult = rejectVal;
setTimeout(function() {
// 当只有catchCallback时,代表直接写的catch,直接触发流程即可
if (_this.catchCallback) {
_this.catchCallback(rejectVal);
// 如果如果没有catchCallback,存在thenCallback,代表peomise直接使用了then
// 此时应该先让then执行来进行本次then函数的跳过,直到找到catch
} else if (_this.thenCallback) {
_this.thenCallback(rejectVal);
} else {
throw ('notfind catch function')
}
});
}
};
if (fn) {
fn(resolve, reject);
} else {
throw ('Promise resolver undefind is not a function')
}
}
// 实现then和catch方法
MyPromise.prototype.then = function(callback) {
var _this = this;
// 实现链式调用,需要return一个新的promise对象
return new MyPromise(function(resolve, reject) {
// 在then函数执行的时候,优先在函数内部注册回调函数任务
// 等待resolve执行的时候,通过注册异步的任务赖在该回调后捕获它
_this.thenCallback = function(val) {
// catch的链式调用复杂,所以可能在catch触发的时候也会触发
if (_this.promiseState == 'rejected') {
// 如果是reject触发的callback,直接调用下一个对象的reject
reject(val);
} else {
var res = callback(val);
// 判断如果某一次then函数返回的是一个rejected的promise对象
// 此时我们需要在这里直接注册catch,并且在catch内部拿到对象的结果
// 然后通过下一个对象的reject链式通知最近的catch执行
if (res instanceof MyPromise && res.promiseState === 'rejected') {
res.catch(function(err) {
reject(err)
})
} else {
resolve(res);
}
}
}
})
}
MyPromise.prototype.catch = function(callback) {
var _this = this
return new MyPromise(function(resolve, reject) {
_this.catchCallback = function(val) {
var res = callback(val);
// catch本次对象的状态是reject,但是如果继续调用,默认触发的还是then
resolve(res);
}
})
}
MyPromise.resolve = function(val) {
return new MyPromise(function(resolve, reject) {
resolve(val)
})
}
MyPromise.reject = function(val) {
return new MyPromise(function(resolve, reject) {
reject(val)
})
}
MyPromise.all = function(promiseArr) {
var resArr = [];
return new MyPromise(function(resolve, reject) {
// MyPromise.all必须等待数组中所有的状态都不为pending才能往下触发
promiseArr.forEach((promiseItem, index) => {
promiseItem.then(function(res) {
resArr[index] = res;
let success = promiseArr.every(item => {
return item.promiseState === 'fulfilled';
})
if (success) {
resolve(resArr)
}
}).catch(function name(err) {
reject(err)
})
});
})
}
MyPromise.race = function(promiseArr) {
return new MyPromise(function(resolve, reject) {
// MyPromise.all必须等待数组中所有的状态都不为pending才能往下触发
promiseArr.forEach((promiseItem, index) => {
promiseItem.then(function(res) {
resolve(res);
}).catch(function name(err) {
reject(err);
})
});
})
}
// 示例5
var pAll1 = new MyPromise(function(resolve, reject) {
setTimeout(() => {
reject('第一个')
}, 1000);
});
var pAll2 = new MyPromise(function(resolve, reject) {
setTimeout(() => {
resolve('第二个')
}, 300);
});
var pAll3 = new MyPromise(function(resolve, reject) {
setTimeout(() => {
resolve('第三个')
}, 2000);
});
MyPromise.all([pAll2, pAll1, pAll3]).then(function(res) {
console.log(res)
}).catch(function(err) {
console.error(err);
});
// 示例1
var mp1 = new MyPromise(function(resolve, reject) {
reject('reject的值')
})
mp1.then(function(res) {
console.log(res);
console.log('then执行');
}).then(function(res) {
console.log(res);
console.log('then执行');
}).then(function(res) {
console.log(res);
console.log('then执行');
}).catch(function(err) {
console.log(err);
console.log('catch执行');
})
// 示例2
var mp2 = new MyPromise(function(resolve) {
setTimeout(() => {
resolve('第一秒')
}, 1000);
}).then(function(res) {
console.log(res);
return new MyPromise(function(resolve) {
setTimeout(() => {
resolve('第二秒')
}, 1000);
})
}).then(function(res) {
console.log(res);
return new MyPromise(function(resolve) {
setTimeout(() => {
resolve('第三秒')
}, 1000);
})
}).then(function(res) {
console.log(res);
})
// 示例3
let MP3 = new MyPromise(function(resolve, reject) {
// resolve('我是promise的值');
resolve(new MyPromise(function(resolve1, reject1) {
resolve1('初始传入的peomise对象')
}));
});
MP3.then(function(res) {
console.log(res);
console.log('then触发')
return 123;
}).then(function(res) {
console.log('第二个then触发');
console.log(res);
return new MyPromise(function(resolve, reject) {
resolve('第二个then的值');
})
}).then(function(res) {
console.log('第三个then触发');
console.log(res);
})
// 示例4
var mp4 = new MyPromise(function(resolve, reject) {
resolve('第一步')
})
mp4.then(function(res) {
console.log(res);
console.log('第一个then');
return MyPromise.reject('中断');
}).then(function(res) {
console.log(res);
console.log('第二个then');
return 3
}).then(function(res) {
console.log(res);
console.log('第三个then');
return 4
}).catch(function(err) {
console.log(err);
console.log('catch执行');
})
</script>
</html>