Promise的基本使用
const pro = new Promise((resolve, reject)=>{
// 未决阶段的处理
// 通过调用resolve函数将Promise推向已决阶段的resolved状态
// 通过调用reject函数将Promise推向已决阶段的rejected状态
// resolve和reject均可以传递最多一个参数,表示推向状态的数据
})
pro.then(data=>{
//这是thenable函数,如果当前的Promise已经是resolved状态,该函数会立即执行
//如果当前是未决阶段,则会加入到作业队列,等待到达resolved状态后执行
//data为状态数据
}, err=>{
//这是catchable函数,如果当前的Promise已经是rejected状态,该函数会立即执行
//如果当前是未决阶段,则会加入到作业队列,等待到达rejected状态后执行
//err为状态数据
})
细节
- 未决阶段的处理函数是同步的,会立即执行
- thenable和catchable函数是异步的,就算是立即执行,也会加入到事件队列中等待执行,并且,加入的队列是微队列
- pro.then可以只添加thenable函数,pro.catch可以单独添加catchable函数
- 在未决阶段的处理函数中,如果发生未捕获的错误,会将状态推向rejected,并会被catchable捕获
- 一旦状态推向了已决阶段,无法再对状态做任何更改
- Promise并没有消除回调,只是让回调变得可控
Promise的其他api
原型成员 (实例成员)
- then:注册一个后续处理函数,当Promise为resolved状态时运行该函数
- catch:注册一个后续处理函数,当Promise为rejected状态时运行该函数
- finally:[ES2018]注册一个后续处理函数(无参),当Promise为已决时运行该函数
构造函数成员 (静态成员)
-
resolve(数据):该方法返回一个resolved状态的Promise,传递的数据作为状态数据
- 特殊情况:如果传递的数据是Promise,则直接返回传递的Promise对象
-
reject(数据):该方法返回一个rejected状态的Promise,传递的数据作为状态数据
-
all(iterable):这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。
-
race(iterable):当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象
模拟Promise
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="./MyPromise.js"></script>
<script>
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
const proms = [];
for (let i = 0; i < 10; i++) {
proms.push(new MyPromise((resolve, reject) => {
setTimeout(() => {
// console.log(i, "完成");
// resolve(i);
if (Math.random() < 0.5) {
console.log(i, "完成");
resolve(i);
} else {
console.log(i, "失败")
reject(i);
}
}, getRandom(1000, 5000));
}))
}
//等到所有的promise变成resolved状态后输出: 全部完成
const pro = MyPromise.race(proms)
pro.then(datas => {
console.log("有一个完成", datas);
})
pro.catch(err => {
console.log("有一个失败", err);
})
</script>
</body>
</html>
const MyPromise = (() => {
const PENDING = "pending",
RESOLVED = "resolved",
REJECTED = "rejected",
PromiveValue = Symbol("PromiseValue"), //状态数据
PromiseStatus = Symbol("PromiseStatus"),
thenables = Symbol("thenables"), //thenable
catchables = Symbol("catchbles"), //catchables
changeStatus = Symbol("changeStatus"),//当前状态
settleHandle = Symbol("settleHandle"), //后续处理的通用函数
linkPromise = Symbol("linkPromise"); //创建串联的Promise
return class MyPromise {
/**
* 改变当前Promise的状态
* @param {*} newStatus
* @param {*} newValue
* @param {*} queue 执行的作业队列
*/
[changeStatus](newStatus, newValue, queue) {
if (this[PromiseStatus] !== PENDING) {
//状态无法变更
return;
}
this[PromiseStatus] = newStatus;
this[PromiveValue] = newValue;
//执行相应队列中的函数
queue.forEach(handler => handler(newValue));
}
/**
*
* @param {*} executor 未决阶段(pending状态)下的处理函数
*/
constructor(executor) {
this[PromiseStatus] = PENDING;
this[PromiveValue] = undefined;
this[thenables] = []; //后续处理函数的数组 -> resolved
this[catchables] = []; //后续处理函数的数组 -> rejected
const resolve = data => {
this[changeStatus](RESOLVED, data, this[thenables]);
}
const reject = reason => {
this[changeStatus](REJECTED, reason, this[catchables]);
}
try {
executor(resolve, reject)
}
catch (err) {
reject(err);
}
}
/**
* 处理 后续处理函数
* @param {*} handler 后续处理函数
* @param {*} immediatelyStatus 需要立即执行的状态
* @param {*} queue 作业队列
*/
[settleHandle](handler, immediatelyStatus, queue) {
if (typeof handler !== "function") {
return;
}
if (this[PromiseStatus] === immediatelyStatus) {
//直接运行
setTimeout(() => {
handler(this[PromiveValue]);
}, 0);
}
else {
queue.push(handler);
}
}
[linkPromise](thenalbe, catchable) {
function exec(data, handler, resolve, reject) {
try {
const result = handler(data); //得到当前Promise的处理结果
if (result instanceof MyPromise) {
result.then(d => {
resolve(d)
}, err => {
reject(err);
})
}
else {
resolve(result);
}
}
catch (err) {
reject(err);
}
}
return new MyPromise((resolve, reject) => {
this[settleHandle](data => {
exec(data, thenalbe, resolve, reject);
}, RESOLVED, this[thenables])
this[settleHandle](reason => {
exec(reason, catchable, resolve, reject);
}, REJECTED, this[catchables])
})
}
then(thenable, catchable) {
return this[linkPromise](thenable, catchable);
}
catch(catchable) {
return this[linkPromise](undefined, catchable);
}
static all(proms) {
return new Promise((resolve, reject) => {
const results = proms.map(p => {
const obj = {
result: undefined,
isResolved: false
}
p.then(data => {
obj.result = data;
obj.isResolved = true;
//判断是否所有的全部完成
const unResolved = results.filter(r => !r.isResolved)
if (unResolved.length === 0) {
//全部完成
resolve(results.map(r => r.result));
}
}, reason => {
reject(reason);
})
return obj;
})
})
}
static race(proms) {
return new Promise((resolve, reject) => {
proms.forEach(p => {
p.then(data => {
resolve(data);
}, err => {
reject(err);
})
})
})
}
static resolve(data) {
if (data instanceof MyPromise) {
return data;
}
else {
return new MyPromise(resolve => {
resolve(data);
})
}
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
})
}
}
})();