补充知识:
- promise一共有三个状态:pending、rejected、fulfilled
- 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
- 一旦状态改变,就不会再变,
Promise
对象的状态改变,只有两种可能:从pending
变为fulfilled
和从pending
变为rejected
一、promise.all
特点:
- 参数是可迭代对象(Iterator),里边的每一项都是promise实例(如果不是,就会先调用下面讲到的
Promise.resolve
方法,将参数转为 Promise 实例,再进一步处理) - 返回值是个promise实例
- 如果全部成功,状态变为resolved, 并且返回值组成一个数组传给回调
- 但凡有一个失败,状态变为rejected, 并将error返回给回调
- 返回结果严格按照传入的promise顺序返回
代码:
function all(iterable) {
return new Promise((resolve, reject) => {
let result = []; // 存放结果
let count = 0; //记录有几个resolve
// 空
if (!iterable || iterable.length === 0) {
resolve([]);
return;
}
for (let i = 0; i < iterable.length; i++) {
let promise = iterable[i];
// 如果不是promise实例,就转成promise
if (!(promise instanceof Promise)) {
promise = Promise.resolve(promise);
}
promise.then(
(value) => {
result[i] = value;
count++;
if (count === iterable.length) {
resolve(result);
}
}
).catch(
(err) => {
reject(err);
}
);
}
});
}
验证:
// 有一个reject验证
let p1 = Promise.resolve(1),
p2 = Promise.reject(2),
p3 = Promise.resolve(3);
all([p1,p2,p3]).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err, 'err')
});
// 2 err
// 所有都resolve验证
let p1 = Promise.resolve(1),
p2 = Promise.resolve(2),
p3 = Promise.resolve(3);
all([p1,p2,p3]).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err, 'err')
});
// [ 1, 2, 3 ] res
// 有非promise验证
let p1 = Promise.resolve(1),
p2 = Promise.resolve(2),
p3 = Promise.resolve(3);
all([0,p1,p2,p3]).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err, 'err')
});
// [ 0, 1, 2, 3 ] res
二、promise.race
race是比赛、竞赛的意思,所以顾名思义,就是看谁快,就返回谁。
特点:
- 参数是可迭代对象(Iterator),里边的每一项都是promise实例(如果不是,就会先调用下面讲到的
Promise.resolve
方法,将参数转为 Promise 实例,再进一步处理) - 返回值是个promise实例
- 有一个实例改变状态(不管是resolve还是reject),就结束,并将该实例的结果返回给回调函数
代码:
function race(iterable) {
return new Promise((resolve, reject) => {
// 空
if (!iterable || iterable.length === 0) {
resolve([]);
return;
}
for (let i = 0; i < iterable.length; i++) {
let promise = iterable[i];
// 如果不是promise实例,就转成promise
if (!(promise instanceof Promise)) {
promise = Promise.resolve(promise);
}
promise.then(
(value) => {
resolve(value);
}
).catch(
(err) => {
reject(err);
}
);
}
});
}
验证:
// 都成功验证
let p1 = Promise.resolve(1),
p2 = Promise.resolve(2),
p3 = Promise.resolve(3);
race([p1,p2,p3]).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err, 'err')
});
// 1 res
// 有失败的验证
let p1 = Promise.reject(1),
p2 = Promise.reject(2),
p3 = Promise.resolve(3);
race([p1,p2,p3]).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err, 'err')
});
// 1 res
三、promise.allSettled
特点:
- 参数是可迭代对象(Iterator),里边的每一项都是promise实例(如果不是,就会先调用下面讲到的
Promise.resolve
方法,将参数转为 Promise 实例,再进一步处理) - 返回值是个promise实例
- 只有所有结果都返回才结束(不管是resolve还是reject),以数组形式返回所有结果,每一个结果是一个对象,包含value和status,ES2020引入
[{ status: "rejected", reason: error1 }, { status: "fulfilled", value: 1 }];
代码:
// 按照规定格式处理返回结果
const formatSettledResult = (success, value) =>
success
? { status: "fulfilled", value }
: { status: "rejected", reason: value };
function allSettled(iterable) {
return new Promise((resolve, reject) => {
let len = iterable.length;
// 空
if (!iterable || len === 0) {
resolve([]);
return;
}
let result = []; // 保存已结束的结果
for (let i = 0; i < len; i++) {
let promise = iterable[i];
// 如果不是promise实例,就转成promise
if (!(promise instanceof Promise)) {
promise = Promise.resolve(promise);
}
promise.then(
(value) => {
result[i] = formatSettledResult(true, value);
if (result.length === len) {
resolve(result);
}
}
).catch(
(err) => {
result[i] = formatSettledResult(false, err);
if (result.length === len) {
resolve(result);
}
}
);
}
});
}
验证:
// 验证
let p1 = Promise.reject(1),
p2 = Promise.reject(2),
p3 = Promise.resolve(3);
allSettled([p1,p2,p3]).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err, 'err')
});
/*[
{ status: 'rejected', reason: 1 },
{ status: 'rejected', reason: 2 },
{ status: 'fulfilled', value: 3 }
] res
*/
四、promise.any
与promise.all正好相反
特点:
- 参数是可迭代对象(Iterator),里边的每一项都是promise实例(如果不是,就会先调用下面讲到的
Promise.resolve
方法,将参数转为 Promise 实例,再进一步处理) - 返回值是个promise实例
- 只要参数实例有一个变成
fulfilled
状态,包装实例就会变成fulfilled
状态;如果所有参数实例都变成rejected
状态,包装实例就会变成rejected
状态,并将结果以数组形式返回 - 不会因为某个 Promise 变成
rejected
状态而结束
代码:
function any(iterable) {
return new Promise((resolve, reject) => {
let len = iterable.length;
// 空
if (!iterable || len === 0) {
resolve([]);
return;
}
let result = []; // 保存rejected的结果
for (let i = 0; i < len; i++) {
let promise = iterable[i];
// 如果不是promise实例,就转成promise
if (!(promise instanceof Promise)) {
promise = Promise.resolve(promise);
}
promise.then(
(value) => {
resolve(value);
}
).catch(
(err) => {
result[i] = err;
if (result.length === len) {
reject(result);
}
}
);
}
});
}
验证:
// 验证
let p1 = Promise.reject(1),
p2 = Promise.reject(2),
p3 = Promise.reject(3);
any([p1,p2,p3]).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err, 'err')
});
// [ 1, 2, 3 ] err
// 验证
let p1 = Promise.reject(1),
p2 = Promise.reject(2),
p3 = Promise.resolve(3);
any([p1,p2,p3]).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err, 'err')
});
// 3 res
总结:以上就是所有内容,是不是觉得一点都不难!! 只要了解每个API的特点,就能很轻松的实现了,不过我这只是简易版,容错性比较差,仅供参考。