前言:本文代码比较多只是学习记录,推荐看这位大佬写的文章更加详细具体
Promise的基本规则
-
Promise 是一个构造函数;
-
Promise 接收一个函数,这个函数的参数,是(resolve, reject),也要求是函数。
-
Promise 返回的对象,包含一个 then 函数, then 函数接收两个参数,这两个参数,一般也是函数。
-
我们再使用 new 关键字调用 Promise 构造函数时,在结束时 如果正确执行, 调用 resolve 方法,将结果放在 resolve 的参数中执行,这个结果可以在后面的then 中的第一个函数参数(onFulfilled)中拿到; 如果错误执行, 调用 reject 方法,将错误信息放在 reject 的参数中执行,这个结果可以在后面的then 中的第二个函数参数(onRejected)中拿到;
Promise 的 status:
pending
- 初始的状态,可改变,
- 一个 promise 在
resolve/reject前都处于这个状态 - 我们可以通过调用
resolve方法或reject方法,让这个 promise , 变成fulfilled/rejected状态;
fulfilled
- 不可变状态
- 在
resolve之后,变成这个状态,拥有一个value
rejected
- 不可变状态
- 在
reject之后,变成这个状态,拥有一个reason
then 函数:
-
参数:
onFulfilled必须是函数类型,如果不是,应该被忽略;onRejected必须是函数类型,如果不是,应该被忽略; -
onFulfilled / onRejected 的特性 在 promise 变成
fulfilled/rejected状态的时候,应该调用onFulfilled/onRejected; 在 promise 变成fulfilled/rejected状态之前,不应该被调用; 只能被调用一次。
第一版
首先我先根据定义写一个最简单的Promise
function L0Promise(execute) {
this.status = 'pending';
this.value = null;
this.reason = null;
// 我们可以通过调用 `resolve` 方法或 `reject` 方法,
// 让这个 promise , 变成 `fulfilled`/`rejected` 状态;
const resolve = (value) => {
if (this.status === 'pending') {
this.value = value;
this.status = 'fulfilled';
}
};
const reject = (reason) => {
if (this.status === 'pending') {
this.reason = reason;
this.status = 'rejected';
}
};
execute(resolve, reject);
};
L0Promise.prototype.then = function (onfulfilled, onrejected) {
//判断是否是函数 不是也给个默认噶不是故意
onfulfilled = typeof onfulfilled === 'function'
? onfulfilled : data => data;
onrejected = typeof onrejected === 'function'
? onrejected : error => { throw error };
if (this.status === 'fulfilled') {
onfulfilled(this.value);
}
if (this.status === 'rejected') {
onrejected(this.reason);
}
};
基本的逻辑写完了 现在让我们来调用一下看看 能不能运行。😀
let promise = new L0Promise((resolve, reject) => {
setTimeout(() => {
resolve('data');
}, 1000)
});
promise.then((data) => {
console.log(data); //undefined
});
哦吼!!并没有满足我们的预期正常工作。是哪里出问题了呢?🤔
第二版
答案: 熟悉执行机制的小伙伴会发现,当我 resolve 的时候, onfulfilled 函数,已经执行过了。所以,我们需要在一个合适的时间去执行 onfulfilled。换句话说,我们需要在一个合适的时间,去通知 onfulfilled 执行。
是不是很熟悉🤔? 这就是发布订阅模式
Promise 支持这种多次.then 运行 但我们第一版就支持第一次。如何解决呢?
function L1Promise(execute) {
this.status = 'pending';
this.value = null;
this.reason = null;
this.onFulfilledArray = [];
this.onRejectedArray = [];
const resolve = (value) => {
setTimeout(() => {
if(this.status === 'pending') {
this.value = value;
this.status = 'fulfilled';
this.onFulfilledArray.forEach(func => func(value));
}
})
};
const reject = (reason) => {
setTimeout(() => {
if(this.status === 'pending') {
this.reason = reason;
this.status = 'rejected';
this.onRejectedArray.forEach(func => func(value));
}
})
};
execute(resolve, reject);
};
L1Promise.prototype.then = function(onfulfilled, onrejected) {
onfulfilled = typeof onfulfilled === 'function'
? onfulfilled : data => data;
onrejected = typeof onrejected === 'function'
? onrejected : error => {throw error};
if(this.status === 'fulfilled') {
onfulfilled(this.value);
}
if(this.status === 'rejected') {
onrejected(this.reason);
}
if(this.status === 'pending') {
this.onFulfilledArray.push(onfulfilled);
this.onRejectedArray.push(onrejected);
}
};
第三版
不知道大家有没有写过类似的代码
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hello');
}, 1000)
});
promise.then((data) => {
console.log(data, 'word');
return data + ' 咸鱼'
}).then(data => {
console.log(data);
return data + ' 咸鱼1'
}).then(data => {
console.log(data);
})
// hello word
// hello 咸鱼
// hello 咸鱼 咸鱼1
但我们的第二版却不行 只能支持一个then,这是为啥呢? Promise是如何支持多个.then 的呢? 其实then 应该返回一个promise 然后把这个promise的结果交给第二个then
function L2Promise(execute) {
this.status = 'pending';
this.value = null;
this.reason = null;
this.onFulfilledArray = [];
this.onRejectedArray = [];
const resolve = (value) => {
setTimeout(() => {
if(this.status === 'pending') {
this.value = value;
this.status = 'fulfilled';
this.onFulfilledArray.forEach(func => func(value));
}
})
};
const reject = (reason) => {
setTimeout(() => {
if(this.status === 'pending') {
this.reason = reason;
this.status = 'rejected';
this.onRejectedArray.forEach(func => func(value));
}
})
};
// try catch
execute(resolve, reject);
};
L2Promise.prototype.then = function(onfulfilled, onrejected) {
onfulfilled = typeof onfulfilled === 'function'
? onfulfilled : data => data;
onrejected = typeof onrejected === 'function'
? onrejected : error => {throw error};
let promise2; // 作为 then 函数的返回值。
if(this.status === 'fulfilled') {
return promise2 = new L2Promise((resolve, reject) => {
setTimeout(() => {
try {
let result = onfulfilled(this.value);
resolve(result);
} catch(e) {
reject(e);
}
})
})
}
if(this.status === 'rejected') {
return promise2 = new L2Promise((resolve, reject) => {
setTimeout(() => {
try {
let result = onrejected(this.reason);
resolve(result);
} catch(e) {
reject(e);
}
})
})
}
if(this.status === 'pending') {
return promise2 = new L2Promise((resolve, reject) => {
this.onFulfilledArray.push(() => {
try {
let result = onfulfilled(this.value);
resolve(result);
}
catch(e) {
reject(e);
}
})
this.onRejectedArray.push(() => {
try {
let result = onrejected(this.reason);
resolve(result);
}
catch(e) {
reject(e);
}
})
})
}
};
总结
其实写到这里 Promise 就基本上差不多了,如果这边都理解了其实面对一般的手写Promise 就都可以了。但是还不太规范如果想要完全符合Promises/A+的规范请大家自行学习了。
还有我只是一个小菜鸡 如果有写的不好的地方,轻喷!!