声明 Promise
首先,promise 是一个类,所以用class来声明。
1. new Promise((resolve, reject)=>{}), 因此要传入一个参数(函数),叫做executor;
2. executor 里面有两个参数,resolve 和 rejecte ,表示成功/失败;
class Promise{
// 构造器
constructor(executor){
// 成功
let resolve = () => {
};
// 失败
let reject = () => {
};
// 立即执行
executor(resolve,reject)
}
}
解决基本状态
官方对Promise有如下规定:
1. Promise 存在三个状态(state):pending、fulfilled、rejected;
2. pending(等待态)为初始态,并可以转化为 fulfilled(成功态)和rejected(失败态);
3. 成功时,不可转为其他状态,并且需要有一个不可改变的值(value) ;
4. 失败时,不可转为其他状态,并且需要有一个不可改变的原因(reason) ;
5. new Promise((resolve, reject)=>{resolve(value)}) resolve为成功,接收value参数,并且改变状态为fulfilled,不可以再次改变;
6. new Promise((resolve, reject)=>{reject(reason)}) reject为成功,接收reason参数,并且改变状态为rejected,不可以再次改变;
7. 若 executor 函数报错,直接执行reject();
class Promise {
constructor(executor) {
// 初始化state为等待态
this.state = 'pending';
//成功的值
this.value = undefined;
//失败的原因
this.reason = undefined;
let resolve = value => {
// state 改变,resolve 调用就会失败
if (this.state === 'pending') {
// resolve调用后,state转化为成功态
this.state = 'fulfilled';
// 储存成功的值
this.value = value;
}
}
let reject = reason => {
// state 改变,reject 调用就会失败
if (this.state === 'pending') {
// resolve调用后,state转化为成功态
this.state = 'rejected';
// 储存成功的值
this.reason = reason;
}
}
// 若 executor 执行报错,则直接调用 reject
try{
executor(resolve,reject);
}catch(err){
reject(err);
}
}
}
then方法
promise 有一个叫做 then 的方法,里面有两个参数:onFulfilled,onRejected,成功返回值,失败返回原因。
1. 当state状态为fulfilled,则执行onFulfilled,传入this.value;
2. 当state状态为rejected,则执行onRejected,传入this.reason;
3. 因此把onFulfilled、onRejected看作函数,则必须分别在fulfilled,rejected之后被调用,value或reason依次作为他们的第一个参数 ;
class Promse {
constructor(executor) {
... }
// then方法,有两个参数 onFulfilled 和 onRejected
then(onFulfilled, onRejected) {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.state === 'fulfilled') {
onFulfilled(this.value)
}
// 状态为rejected,执行onRejected,传入失败的原因
if (this.state === 'rejected') {
onRejected(this.reason)
}
}
}
功能已经基本实现,但无法针对setTimeout
解决异步实现
现在可以基本实现简单的同步代码,但是当resolve在setTimeout内执行,then这时的state还是pending的状态,所以我们需要在then调用的时候,将失败和成功存到各自的数组,一旦reject或者resolve,就调用他们
类似订阅发布,先将then里面的两个函数储存起来,由于一个promise可以有多个then,所以存在同一个数组内
// 解决异步调用
class Promise {
constructor(executor){
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
// 成功存放的数组
this.onResolvedCallbacks = [];
// 失败存放的数组
this.onRejectedCallbacks = [];
let resolve = value =>{
if(this.state === 'pending'){
this.state = 'fulfilled'
this.value = value
// 一旦resolve执行,调用成功数组的函数
this.onResolvedCallbacks.forEach(fn => fn())
}
}
let reject = reson => {
if(this.state === 'padding'){
this.state = 'fulfilled'
this.reason = reson
// 一旦reject执行,调用失败数组的函数
this.onRejectedCallbacks.forEach(fn => fn())
}
}
then(onFulfilled,onRejected){
if(this.state === 'fulfilled'){
onFulfilled(this.value)
};
if(this.state === 'rejected'){
onRejected(this.reason)
}
// 当状态state为pending时
if(this.state === 'pending'){
// onFulfilled 传入到成功数组
this.onResolvedCallbacks.push(()