并发(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)