let p1 = new Promise((resolve, reject) => {
resolve('p1')
})
let p2 = new Promise((resolve, reject) => {
reject('p2')
})
let p3 = new Promise((resolve, reject) => {
reject('p3')
})
// 错误的做法
Promise.all([p1, p2, p3])
.then(values => {
console.log(values) // 上面三个Promise有其中任意一个报错后,这里就不返回了
})
.catch(err => {
console.log(err) // p2
})
// 正确的做法1,返回错误写死
Promise.allSettled([p1, p2, p3].map(p => p.catch(e => '出错后返回的值'))).then(
values => {
console.log(values)
}
)
// 正确的做法2,捕获正常返回错误
Promise.allSettled([p1, p2, p3]).then(values => {
console.log(values)
})
//错误示例
const fetchDataA = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is A')
}, 1000)
})
}
const fetchDataB = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is B')
}, 1000)
})
}
const fetchDataC = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is C')
}, 1000)
})
}
try {
const dataA = await fetchDataA()
console.log('dataA is ->', dataA)
} catch (err) {
console.log('err is ->', err)
}
try {
const dataB = await fetchDataB()
console.log('dataB is ->', dataB)
} catch (err) {
console.log('err is ->', err)
}
try {
const dataC = await fetchDataC()
console.log('dataC is ->', dataC)
} catch (err) {
console.log('err is ->', err)
}
const fetchDataA = () => {
return new Promise((resolve, reject) => {
reject('reject错误1')
})
}
const fetchDataB = () => {
return new Promise((resolve, reject) => {
resolve('dataB is ->')
})
}
// 正确做法,抽离成公共方法,去捕获错误
const awaitWrap = promise => {
return promise.then(data => [null, data]).catch(err => [err, null])
}
const [err, data] = await awaitWrap(fetchDataA())
const [err2, data2] = await awaitWrap(fetchDataB())
console.log('err', err)
console.log('err2', err2)
console.log('---:')
console.log('data', data)
console.log('data2', data2)
function awaitWrap<T, U = any>(
promise: Promise<T>
): Promise<[U | null, T | null]> {
return (
promise.then <
[null, T] >
((data: T) => [null, data]).catch <
[U, null] >
(err => [err, null])
)
}
map 的返回值始是 promise 数组,这是因为异步函数总是返回 promise
async function test() {
console.log('start')
const res = ['js', 'vue', 'node', 'react'].map(async item => {
return await getSkillPromise(item)
})
const resPromise = await Promise.all(res)
console.log(resPromise)
}
test()
在处理诸如文件上传等场景时,可能需要限制同时进行的异步操作数量以避免系统资源耗尽
async function asyncPool(poolLimit, array, iteratorFn) {
const result = []
const executing = []
for (const item of array) {
const p = Promise.resolve().then(() => iteratorFn(item, array))
result.push(p)
if (poolLimit <= array.length) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1))
executing.push(e)
if (executing.length >= poolLimit) {
await Promise.race(executing)
}
}
}
return Promise.all(result)
}
// 示例
async function uploadFile(file) {
// 文件上传逻辑
}
async function limitedFileUpload(files) {
return asyncPool(3, files, uploadFile)
}
// 异步递归函数
async function asyncRecursiveSearch(nodes) {
for (const node of nodes) {
await asyncProcess(node)
if (node.children) {
await asyncRecursiveSearch(node.children)
}
}
}
// 示例
async function asyncProcess(node) {
// 对节点进行异步处理逻辑
}
class ApiClient {
constructor() {
this.value = null
}
async firstMethod() {
this.value = await fetch('/first-url').then(r => r.json())
return this
}
async secondMethod() {
this.value = await fetch('/second-url').then(r => r.json())
return this
}
}
// 使用方式
const client = new ApiClient()
const result = await client.firstMethod().then(c => c.secondMethod())
import plimit from 'p-limit'
const limit = plimit(10)
requestList.forEach(async item => {
const res = await limit(item)
console.log(res)
})
// 运行池
const pool = new Set()
// 等待队列
const waitQueue = []
/**
* @description: 限制并发数量的请求
* @param {*} reqFn:请求方法
* @param {*} max:最大并发数
*/
const request = (reqFn, max) => {
return new Promise((resolve, reject) => {
// 判断运行吃是否已满
const isFull = pool.size >= max
// 包装的新请求
const newReqFn = () => {
reqFn()
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
.finally(() => {
// 请求完成后,将该请求从运行池中删除
pool.delete(newReqFn)
// 从等待队列中取出一个新请求放入等待运行池执行
const next = waitQueue.shift()
if (next) {
pool.add(next)
next()
}
})
}
if (isFull) {
// 如果运行池已满,则将新的请求放到等待队列中
waitQueue.push(newReqFn)
} else {
// 如果运行池未满,则向运行池中添加一个新请求并执行该请求
pool.add(newReqFn)
newReqFn()
}
})
}
requestList.forEach(async item => {
const res = await request(item, 10)
console.log(res)
})
const uniqueArray = Array.from(
new Map(mergedArray.map(item => [item.id, item])).values()
)