一、 Promise原理
借助状态机的概念理解Promise原理,假定Promise实例是一个状态机。
1.1 Promise 状态机:
Promise状态机是Promise实现异步编程的核心手段,这个状态机拥有三种状态status,分别是
pending----待定
fulfilled----兑现(亦称解决、resolved)
rejected----拒绝
Promise状态机的状态status转换只有两种,且这两种转换的过程是单向不可逆的,即
pending ----> fulfilled <=====> 对应的状态转变函数是resolve
pending ----> rejected <=====> 对应的状态转变函数是reject
当我们的状态机发生了转变,我们应该给出相应的处理结果(如fulfilled时,应该返回相应的处理值value;rejected时,应该给出拒绝的理由reason)
1.2 executor
executor接受两个状态转变函数(resolve, reject)作为参数。
当通过new 来生成一个Promise实例时,需要我们传入一个executor 函数,该executor的作用是指定Promise
状态机的状态转换规则,如状态机在什么时候resolve,并确定fulfilled后应该返回什么值;在什么时候reject,
在rejected时,应给出拒绝的原因。即executor中的代码需要编程人员自行组织。
注意:executor函数中的代码是按照正常执行顺序执行的。
1.3 thenable 接口
在ES中暴露的异步结构中,任何Promise对象都有一个then方法。
1.4 Promise实例的相关方法
then、catch、finally这三个实例函数的执行时机是在Promise状态机的状态发生转变后执行,即异步执行。
then(onFulfilled、onRejected):
接受两个处理函数onFulfilled、onRejected作为参数。
当status为fulfilled时,执行onFulfilled。
当status为rejected是,执行onRejected。
then的显式返回值会被包装成在个Promise实例中。
catch(onRejected):
接受一个处理函数onRejected作为参数、在rejected时会执行;
catch的显式返回值会被包装成在个Promise实例中。
finally(onFinally):
接受一个任意处理函数作为参数、无论fulfilled或是rejected都会执行
1.5 Promise的静态方法
resolve(value):
生成一个fulfilled的Promise实例。
reject(reason):
生成一个rejected的Promise实例。
all(args):
接受一个Promise实例数组,如果所有Promise实例的状态都为fulfilled,
生成一个fulfilled的Promise实例;否则生成一个rejected的Promise实例。
这个方法可用于并发执行。
race(args):
接受一个Promise实例数组,生成一个Promise实例,数组中哪个实例的状态先转变,
则生成的实例的状态与先发生状态转变的实例的状态一致。
二、简陋实现一个Promise类
// 通过上述原理实现一个简陋的Promise类、用setTimeout模拟异步(这种方式有很大的问题)
/**************************************************Promise概述********************************************
* @title:Promise原理
* @content:
* 理解Promise的两个核心概念:Promise状态机、executor
* Promise 状态机:
* Promise状态机是Promise实现异步编程的核心手段,这个状态机拥有三种状态status,分别是
* pending----待定
* fulfilled----兑现(亦称解决、resolved)
* rejected----拒绝
* Promise状态机的状态status转换只有两种,且这两种转换的过程是单向不可逆的,即
* pending ----> fulfilled <=====> 对应的状态转变函数是resolve
* pending ----> rejected <=====> 对应的状态转变函数是reject
* 当我们的状态机发生了转变,我们应该给出相应的处理结果(如fulfilled时,应该返回相应的处理值value;
* rejected时,应该给出拒绝的理由reason)
* Promise executor:executor接受两个状态转变函数(resolve, reject)作为参数
* 当通过new 来生成一个Promise实例时,需要我们传入一个executor 函数,该executor的作用是指定Promise
* 状态机的状态转换规则,如状态机在什么时候resolve,并确定fulfilled后应该返回什么值;在什么时候reject,
* 在rejected时,应给出拒绝的原因。即executor中的代码需要编程人员自行组织。
* 注意:executor函数中的代码是按照正常执行顺序执行的。
* thenable 接口:
* 在ES中暴露的异步结构中,任何Promise对象都有一个then方法。
* Promise实例的api函数
* then、catch、finally这三个实例函数的执行时机是在Promise状态机的状态发生转变后执行,即异步执行。
* then:接受两个处理函数onFulfilled、onRejected作为参数。
* 当status为fulfilled时,执行onFulfilled。
* 当status为rejected是,执行onRejected。
* then的显式返回值会被包装成在个Promise实例中
* catch: 接受一个处理函数onRejected作为参数、在rejected时会执行;
* catch的显式返回值会被包装成在个Promise实例中。
* finally: 接受一个任意处理函数作为参数、无论fulfilled或是rejected都会执行
* @date:2023/4/5
* ****************************************************************************************************/
// 通过上述原理实现一个简陋的Promise类、用setInterval模拟异步(轮询状态)
class MyPromise {
/**MyPromsie class
* @members:
* status: Promise状态机的状态,初始为pending。
* value: 状态机的状态为fulfilled时,处理的返回值。
* reason: 状态机的状态为rejected时,拒绝的原因。
* @methods:
* constructor(executor):构造函数,executor函数作为实例化参数,该executor的作用是指定Promise状态机的转换规则;
* 如状态机在什么时候resolve,并确定fulfilled后应该返回什么值;
* 状态机在什么时候reject,在rejected时,应给出拒绝的原因。
* @instance-methods:
* then(onFulfilled, onRejected):接受两个处理函数onFulfilled、onRejected作为参数。
* 当status为fulfilled时,执行onFulfilled。
* 当status为rejected是,执行onRejected。
* then的显示返回值会被包装在一个新Promise实例中。
* catch(onRejected):接受一个处理函数onRejected作为参数、在rejected时会执行;
* catch的显示返回值会被包装在一个新Promise实例中。
* finally(onFinally):接受一个任意处理函数作为参数、无论fulfilled或是rejected都会执行,
* 返回值是当前Promise实例。
* @static-methods:
* resolve(value): 生成一个fulfilled的Promise实例。
* reject(reason): 生成一个rejected的Promise实例。
* all(args): 接受一个Promise实例数组,如果所有Promise实例的状态都为fulfilled,
* 生成一个fulfilled的Promise实例;否则生成一个rejected的Promise实例。
* 这个方法可用于并发执行。
* race(args): 接受一个Promise实例数组,生成一个Promise实例,数组中哪个实例的状态先转变,
* 则生成的实例的状态与先发生状态转变的实例的状态一致。
* */
constructor(executor) {
this.value = undefined;
this.reason = undefined;
this.status = 'pending';
// 定义两个状态转变函数
const resolve = (value) => {
if (this.status === 'pending') {
// 保证状态机的状态转换是不可逆的
this.status = 'fuifilled';
this.value = value;
}
}
const reject = (reason) => {
if (this.status === 'pending') {
// 保证状态机的状态转换是不可逆的
this.status = 'rejected';
this.reason = reason;
}
}
// 执行状态转变规则函数
executor(resolve, reject);
}
catch (onRejected) {
// catch其实就是一个语法糖
return this.then(() => {}, onRejected);
}
then(onFulfilled, onRejected) {
const self = this;
return new MyPromise((resolve, reject) => {
let exeFn = null; // 回调函数
let re = null; // 回调函数的返回值, 需要将其包装在一个Promise实例中
let valueOrReason = null;
// 使用setInterval轮询Promise状态
let timer = setInterval(() => {
if (self.status === 'fuifilled' && typeof onFulfilled === 'function') {
// fulfilled 状态
exeFn = onFulfilled;
valueOrReason = self.value;
} else if (self.status === 'rejected' && typeof onRejected === 'function') {
// rejected 状态
exeFn = onRejected;
valueOrReason = self.reason;
}
// 状态转变
if (self.status !== 'pending') {
typeof exeFn === 'function' && (re = exeFn(valueOrReason));
resolve(re);
// 清除定时器
clearInterval(timer);
}
});
})
}
finally(fn) {
// 轮询状态
let timer = setInterval(() => {
// 状态转变
if (this.status !== 'pending') {
typeof fn === 'function' && fn();
// 清除定时器
clearInterval(timer);
}
})
// 返回实例本身
return this;
}
static resolve(value) {
return new MyPromise((resolve, reject) => {
resolve(value);
});
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
static all(args /*Promise array*/ ) {
const len = args.length;
const results = []; // 并发处理的结果
let count = 0; // fulfilled的promise数量
return new MyPromise((resolve, reject) => {
args.forEach(p => {
p.then((data) => {
count += 1;
data && results.push(data);
if (count === len) {
resolve(results);
}
}, (reason) => {
reject(reason);
})
})
})
}
static race(args /*Promise array*/ ) {
return new MyPromise((resolve, reject) => {
args.forEach(p => {
p.then((value) => {
resolve(value);
}, (reason) => {
reject(reason);
});
})
})
}
}
const p1 = new MyPromise((resolve, reject) => {
console.log('begin1');
setTimeout(() => {
resolve('fail');
}, 3000);
console.log('end1');
});
const p2 = new MyPromise((resolve, reject) => {
console.log('begin2');
setTimeout(() => {
resolve('ok');
}, 4000)
console.log('end2');
});
const p3 = new MyPromise((resolve, reject) => {
console.log('begin3');
setTimeout(() => {
resolve('ok');
})
console.log('end3');
});
const p = MyPromise.all([p1, p2, p3]);
p.then((val) => {
console.log(val);
}, (rea) => {
console.log(rea);
}).finally(() => {
console.log('over');
}).then(() => {
console.log('ok');
console.log(p);
});
console.log(p);
Promise原理与简易实现解析
文章详细介绍了Promise的工作原理,包括其状态机模型(pending、fulfilled、rejected),executor函数的角色,以及then、catch和finally方法的使用。此外,还提供了一个简单的Promise类实现,通过setInterval模拟异步操作。最后展示了Promise.all和Promise.race的静态方法,并用实例解释了它们的功能。
1175

被折叠的 条评论
为什么被折叠?



