并发(concurrency)和 并行(parallelism)区别
并发: 至少两个线程同时处理中,可以看作广义的并行或虚拟并行。
并行: 至少2个线程同时执行
代码实现
定义2个异步函数
function fp1() {
return new Promise((r) => {
setTimeout(() => {
r('')
}, 1000)
})
}
function fp2() {
return new Promise((r) => {
setTimeout(() => {
r('')
}, 3000)
})
}
串行实现
async function ss() {
await fp1()
await fp2()
// 等效实现
fp1().then(() => {
fp2().then()
})
}
并发实现
async function cc() {
const p1 = fp1()
const p2 = fp2()
await p1
await p2
// 等效实现
await Promise.all([fp1(), fp2()])
}
await关键字使得当前函数执行被暂停,直到promise settles并且返回结果。
在ES规范上没查到这种实现方式的直观描述,可能是浏览器自身行为。
await 可以使用Thenable对象
class Thenable {
constructor() {}
then(r) {
setTimeout(() => r(''), 1000)
}
}
async await 并发缺点
1、对 reject 状态不正常捕获
promise 链不是一次就构建好的,而是分阶段构造的,因为控制是先后从 async 函数获取和返回的。
例如,在下面代码中,即使在 promise 链中进一步配置了 .catch 方法处理,也会抛出一个未处理的 promise rejection 错误。这是因为p2直到控制从p1返回后才会连接到 promise 链。
async function fn() {
const p1 = new Promise((r) => {
setTimeout(() => r(''), 3000)
})
const p2 = new Promise((undefined, rej) => {
setTimeout(() => rej('rej'), 1000)
})
await p1
await p2
}
// 不能正常捕获rej
fn().catch(console.log)