文章目录
1. promise的异常捕获
- 如果异步操作抛出错误,状态就会变为
rejected
,就会调用catch()
方法指定的回调函数,处理这个错误 then()
方法指定的回调函数,如果运行中抛出错误,也会被catch()
方法捕获- 如果
Promise
状态已经变成resolved
,再抛出错误是无效的。promise状态只能变一次 - 如果没有使用
catch()
方法指定错误处理的回调函数,Promise
对象抛出的错误不会传递到外层代码,即不会有任何反应。 - 『冒泡』:会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。
catch()
返回一个promise
对象,后面可以继续跟then()
方法
2. 原生实现promise
特性:
new Promise
接受一个函数executor
executor
参数为resolve
和reject
resolve
可以将promise
对象的状态变为成功状态
reject
可以将promise
对象的状态变为失败状态promise
对象的then
方法来注册成功状态或者失败状态要执行的函数then
可以链式调用,then方法返回promise对象,状态取决于上一个promise的对象的状态resolve
可以接受一个简单值也可以接受一个promise
对象,当传入的是一个promise对象时,只有当该对象成功或失败,resolve才会成功- then中成功或失败执行的函数的返回值
- 有简单类型返回值,作为then方法返回的promise对象的成功状态的值
- 当返回一个thenable对象(带有then方法的对象)的时候,只有是成功状态才能执行下一个then
使用ES6的面向对象方式
class MyPromise {
constructor(executor) {
this.initValue()
this.initBind()
try {
executor(this.resolve, this.reject)
}
catch(err) {
this.reject(err)
}
}
initValue() {
this.PromiseState = 'pending'
this.PromiseResult = undefined
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
}
initBind() {
// resolve函数的this永远指向MyPromise实例
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
}
resolve(value) {
if (this.PromiseState !== 'pending') return
this.PromiseState = 'fulfilled'
this.PromiseResult = value
while(this.onFulfilledCallbacks.length) {
this.onFulfilledCallbacks.shift()(this.PromiseResult)
}
}
reject(value) {
if (this.PromiseState !== 'pending') return
this.PromiseState = 'rejected'
this.PromiseResult = value
while(this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(this.PromiseResult)
}
}
then(onFulfilled, onRejected) {
onFulfilled = onFulfilled instanceof Function ? onFulfilled : value => value
onRejected = onRejected instanceof Function ? onRejected : error => { throw(error) }
// 链式调用,必须返回一个promise
return new MyPromise((resolve, reject) => {
setTimeout(() => {
const resolvePromise = (cb) => {
try {
// 当前的promise状态取决于上一个方法的执行结果(也就是onFulfilled和onRejected的执行结果)
const result = cb(this.PromiseResult)
// 如果onFulfilled函数返回一个promise,那么需要看then之后的结果
if (result instanceof MyPromise) {
result.then(resolve, reject)
}
// 如果onFulfilled函数返回一个普通数据,那么直接resolve置为成功
else {
resolve(result)
}
}
catch(error) {
reject(error)
throw new Error(err)
}
}
if (this.PromiseState === 'fulfilled') {
resolvePromise(onFulfilled)
}
else if (this.PromiseState === 'rejected') {
resolvePromise(onRejected)
}
else if (this.PromiseState === 'pending') {
this.onFulfilledCallbacks.push(onFulfilled.bind(this))
this.onRejectedCallbacks.push(onRejected.bind(this))
}
})
})
}
}
3. promise.all()
接受一个数组,且数组中每一项都是promise
的实例,该函数返回值也是一个promise
的实例,当数组中所有的项都fulfilled
才会执行then()
,否则只要有一个rejected
,那么该状态就会变为rejected
原生实现:
function myPromiseAll(iterable) {
return new Promise((resolve,reject) => {
const promises = Array.from(iterable);
// 定义Promise对象resolve的数组
const result = [];
// 定义一个计数器用来判断是否所有的promise执行完毕
let count = 0;
// 并发执行每一个promise
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(res => {
result[i] = res;
count++;
if (count === promises.length) {
resolve(result);
}
}).catch(err => reject(err))
}
})
}
var p1=Promise.resolve(1),
p2=Promise.resolve(2),
p3=Promise.resolve(3);
myPromiseAll([p1,p2,p3]).then(function(value){
console.log(value)
})
4. promise.race()
接收值和返回值和promise.all()
完全一样。
只要有一个状态改变,不管是fulfilled
还是rejected
,该状态都会随着改变。
function myPromiseRace(promises) {
return new Promise((resolve, reject) => {
promises.forEach(promise => {
if (promise instanceof MyPromise) {
promise.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(promise)
}
})
})
}
5. promise.allSettled()
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
把每一个Promise的结果,集合成数组,返回
Promise.myAllSettled = function(promises) {
return new Promise(function(resolve) {
const results = [];
let resolvedCount = 0;
const count = promises.length;
promises.forEach((curPro, index) => {
Promise.resolve(curPro).then(
(data) => {
resolvedCount++;
results[index] = {
status: "fullfilled",
value: data,
};
},
(reason) => {
resolvedCount++;
results[index] = {
status: "rejected",
reason,
};
})
.finally(() => {
if (resolvedCount >= count) {
resolve(results);
}
});
})
})
}
6. promise.any
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
如果有一个Promise成功,则返回这个成功结果
如果所有Promise都失败,则报错
function myPromiseAny(promises) {
return new Promise((resolve, reject) => {
let count = 0
promises.forEach((promise) => {
promise.then(val => {
resolve(val)
}, err => {
count++
if (count === promises.length) {
reject(new AggregateError('All promises were rejected'))
}
})
})
})
}
}
7. 实际运用题
- 封装一个request,当失败时可以进行重试,可以设置重试次数和间隔时间,promise.retry()
function request(options, retryTimes = 3, time = 3000) {
return new Promise((resolve, reject) => {
const retry = function(resolve, reject){
fetch(options).then(() => {
resolve();
}).catch(() => {
retryTimes--;
if (retryTimes >= 0) {
setTimeout(() => {
retry(resolve, reject);
}, time)
}
else reject();
})
}
retry(resolve, reject);
});
}
request('https://example.com/api/data', 3, 1000)
.then(response => {
console.log('成功了')
})
.catch(error => {
console.log('失败!!')
});
8. async await实现promise.all()
async function myPromiseAll(arr) {
let arr1 = [];
try {
for (let i = 0; i < arr.length; i++) {
let h = await arr[i]
arr1.push(h)
}
} catch (err) {
}
return arr1
}
myPromiseAll().then(res => {
console.log(res);
});