本人最近在学习 promise 的相关内容与大家分享,若有不对的地方欢迎大家指正,一起学习进步
一、写一个同步的 promise
1、new Promise((resolve,reject)=>{}) 传入的是一个 executor ,且参数传入后就同步执行
2、executor 有两个参数,resolve/reject且都可以执行,所以都是函数
function Promise (executor){ // 构造对象
// 初始化参数
this.status = 'pending';
this.value = null;
this.reason = null;
// 定义 resolve
const resolve = value =>{
if(this.status === 'pending'){
this.status = 'rsolved';
this.value = value;
}
}
// 定义 reject
const reject = reason => {
if(this.status === 'pending'){
this.status = 'rejected';
this.reason =reason;
}
}
// 立即执行
executor(resolve,reject);
}
// promise 的 then 方法
Promise.prototype.then = function(onFulfilled,onRejected){
if(this.status === 'resolved'){
onFulfilled(this.value);
}
if(this.status === 'rejected'){
onRejected(reason);
}
}
掌握这些内容就可以初出江湖了
二、解决异步调用问题
1、当 executor 中存在 setTimeout 等方法时会产生异步调用,此时我们需要将onFulfilled()/onRejected(),放到一个数组中等 executor 中的内容出结果后再进行调用
2、then 后定义的内容是异步执行的,需要对其中的内容使用process.nextTick() 方法进行处理
function Promise (executor){
this.status = 'pending';
this.value = null;
this.reason = null;
// 添加数组当 executor 中异步时,保存函数
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = value =>{
if(this.status === 'pending'){
this.status = 'resolved';
this.value = value;
// 当 executor 出结果时调用函数
this.onFulfilledCallbacks.map(callback=>{
callback(this.value);
});
}
}
const reject = reason => {
if(this.status === 'pending'){
this.status = 'rejected';
this.reason =reason;
// 当 executor 出结果时调用函数
this.onRejectedCallbacks.map(callback=>{
callback(this.reason);
});
}
}
executor(resolve,reject);
}
Promise.prototype.then = function(onFulfilled,onRejected){
// 添加 process.nextTick() 增加异步
if(this.status === 'resolved'){
process.nextTick(()=>{
onFulfilled(this.value);
})
}
if(this.status === 'rejected'){
process.nextTick(()=>{
onRejected(this.reason);
})
}
// 在 status 是 pending 状态下向数组添加属性
if(this.status === 'pending'){
this.onFulfilledCallbacks.push(
process.nextTick(()=>{
onFulfilled(this.value);
})
)
this.onRejectedCallbacks.push(
process.nextTick(()=>{
onRejected(this.reason);
})
)
}
}
还没完,重头戏刚刚开始
三、解决链式调用
我们常用的 new Promise().then().then() 就是链式调用,常用来解决回调地狱
链式调用中分三种情况
1、then() 的参数中没有定义 onFulfilled/onRejected 时
2、then() 的参数中,返回的不是一个 promise 或无返回值时
3、then() 的参数中返回一个 promise
对应这三种情况 then 返回的 promise (这里称之为 P2)也存在三种不同的状态,反别是
1、将上一层的 promise 的 data 传给 P2
2、将这非 promise 的内容作为 data 传给 P2
3、将参数中返回的 promise 的 data 传给 P2
所以现在要构建一个 P2 且要将上述的三种情况串在一起,根据它们的状态判断 P2 的状态
上代码
function Promise (executor){
this.status = 'pending';
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = value =>{
if(this.status === 'pending'){
this.status = 'resolved';
this.value = value;
this.onFulfilledCallbacks.map(callback=>{
callback(this.value);
});
}
}
const reject = reason => {
if(this.status === 'pending'){
this.status = 'rejected';
this.reason =reason;
this.onRejectedCallbacks.map(callback=>{
callback(this.reason);
});
}
}
executor(resolve,reject);
}
Promise.prototype.then = function(onFulfilled,onRejected){
// case1: 如果未定义 onFulfilled/onRejected 自动初始化
if(typeof onFulfilled !== 'function'){
onFulfilled = value => value;
}
if(typeof onRejected !== 'function'){
onRejected = err => {throw err;}
}
// case2:/case3: 定义了 onFulfilled/onRejected
// P2 的状态由 then 中的参数状态决定
// 将 then 中的参数表达式命名为 P3
// 所以(P3)then 中的参数表达式必须写在P2中(只有在P2中才能看到P2的 resolve/reject)
let p2 = new Promise((resolve, reject)=>{
if(this.status === 'resolved'){
process.nextTick(()=>{
try {
let P3 = onFulfilled(this.value);
// 建立 P2 与 P3 的联系
resolvePromiseRelation(p2,P3,resolve,reject);
} catch (e) {
reject(e);
}
})
}
if(this.status === 'rejected'){
process.nextTick(()=>{
try {
let P3 = onRejected(this.reason);
// 建立 P2 与 P3 的联系
resolvePromiseRelation(p2,P3,resolve,reject);
} catch (e) {
reject(e);
}
})
}
if(this.status === 'pending'){
this.onFulfilledCallbacks.push(() =>{
process.nextTick(()=>{
try {
let P3 = onFulfilled(this.value);
// 建立 P2 与 P3 的联系
resolvePromiseRelation(p2,P3,resolve,reject);
} catch (e) {
reject(e);
}
})
})
this.onRejectedCallbacks.push(()=>{
process.nextTick(()=>{
try {
let P3 = onRejected(this.reason);
// 建立 P2 与 P3 的联系
resolvePromiseRelation(p2,P3,resolve,reject);
} catch (e) {
reject(e);
}
})
})
}
});
return p2;
}
// 建立 P2 与 P3 的连接
function resolvePromiseRelation(P2,P3,P2Resolve,P2Reject){
// 如果 P2 === P3 会陷入死循环
if(P2 === P3){
return P2Reject(new TypeError('Dead cycle P2 = P3'));
};
let called = false;
// 判断 P3 是个什么东西
if(P3 !== null && (typeof P3 === 'function' || typeof P3 === 'object')){
try {
let then = P3.then;
if(typeof then === 'function'){
// 说明 P3 是一个 promise 对象
then.call(P3, data => {
// 运行一次之后本次递归不能再来运行
if(called) return;
called = true;
// 递归保证 data 中不是一个 promise 对象
resolvePromiseRelation(P3,data,P2Resolve,P2Reject);
}, err => {
// 当出错后不再进行递归
if(called) return;
called = true;
P2Reject(err);
});
}else{
// case2: 返回的不是 promise 对象
P2Resolve(P3);
};
} catch (e) {
// 当出错后不再进行递归
if(called) return;
called = true;
P2Reject(e);
}
}else{
// case2: 返回的不是 promise 对象
P2Resolve(P3);
};
}
还没结束,继续ing...
...
...
此时产生一个问题,若 resolve 的参数是一个 promise 对象时,程序状态不会根据此对象状态改变,会将这个 promise 对象内容返回,这不是我们希望看到的!
此时我们需要对进入进入 resolve 的东西进行区分,若进入的是 promise 对象需要对其不断进行递归,直到进入的不再是 promise 对象
代码更改后状态
function Promise (executor){
this.status = 'pending';
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// 由于 resolve 存在递归所以需要 called 监视状态
this.called = false;
const _resolve = value =>{
this.status = 'resolved';
this.value = value;
this.onFulfilledCallbacks.map(callback=>{
callback(this.value);
});
}
const reject = reason => {
if(this.status === 'pending'&& !this.called ){
this.caiied = true;
this.status = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.map(callback=>{
callback(this.reason);
});
}
}
// resolve 给入的有可能是一个 promise 对象,若是 promise 需要进行处理
const resolve = value =>{
// 进入时检测 called 的状态
if(this.status === 'pending' && !this.called ){
this.caiied = true;
// called 防止出错后递归不停止
let called = false;
if(value !== null && (typeof value === 'function' || typeof value === 'object')){
try {
let then = value.then;
if(typeof then === 'function'){
then.call(value, data => {
if(called) return;
called = true;
// 递归前恢复 this.called 的状态防止无法递归
this.called = false;
// data 还可能是 promise 对象,所以再进行递归
resolve(data);
},err => {
if(called) return;
called = true;
// 递归前恢复 this.called 的状态防止无法递归
this.called = false;
reject(err);
});
}else{
_resolve(value);
};
} catch(e) {
if(called) return;
called = true;
// 递归前恢复 this.called 的状态防止无法递归
this.called = false;
reject(e);
}
}else{
_resolve(value);
};
}
}
executor(resolve,reject);
}
Promise.prototype.then = function(onFulfilled,onRejected){
if(typeof onFulfilled !== 'function'){
onFulfilled = value => value;
}
if(typeof onRejected !== 'function'){
onRejected = err => {throw err;}
}
let p2 = new Promise((resolve, reject)=>{
if(this.status === 'resolved'){
process.nextTick(()=>{
try {
let P3 = onFulfilled(this.value);
resolvePromiseRelation(p2,P3,resolve,reject);
} catch (e) {
reject(e);
}
})
}
if(this.status === 'rejected'){
process.nextTick(()=>{
try {
let P3 = onRejected(this.reason);
resolvePromiseRelation(p2,P3,resolve,reject);
} catch (e) {
reject(e);
}
})
}
if(this.status === 'pending'){
this.onFulfilledCallbacks.push(() =>{
process.nextTick(()=>{
try {
let P3 = onFulfilled(this.value);
resolvePromiseRelation(p2,P3,resolve,reject);
} catch (e) {
reject(e);
}
})
})
this.onRejectedCallbacks.push(()=>{
process.nextTick(()=>{
try {
let P3 = onRejected(this.reason);
resolvePromiseRelation(p2,P3,resolve,reject);
} catch (e) {
reject(e);
}
})
})
}
});
return p2;
}
function resolvePromiseRelation(P2,P3,P2Resolve,P2Reject){
if(P2 === P3){
return P2Reject(new TypeError('Dead cycle P2 = P3'));
};
let called = false;
if(P3 !== null && (typeof P3 === 'function' || typeof P3 === 'object')){
try {
let then = P3.then;
if(typeof then === 'function'){
then.call(P3, data => {
if(called) return;
called = true;
resolvePromiseRelation(P3,data,P2Resolve,P2Reject);
}, err => {
if(called) return;
called = true;
P2Reject(err);
});
}else{
P2Resolve(P3);
};
} catch (e) {
if(called) return;
called = true;
P2Reject(e);
}
}else{
P2Resolve(P3);
};
}
终于 promise 代码写完了,紧接着就是 promise 的成员函数和方法....
剩下的代码下次更新....
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!