07 CORDIS / EVENT DISPATCH
监听器执行了,调用方等到了吗?
切换同一组演示输入,沿时间向下读。关注两件事:后续监听器是否运行,调用方何时取得结果。
01 / 派发方法
02 / 输入
前四种:A 返回 Promise(放行后为 undefined),B 返回 0,C 返回 last。
waterfall:独立的 next 包装组;终点为 base,返回时依次追加 C、B、A。异常输入均在 A 进入时直接抛错。
emit正常结果
A 尚未完成,派发已返回
emit 会调用 B、C,但不收集 A 的 Promise。外层 await emit 也无法补齐这份等待。
- 谁被调用
- A、B、C
- 等待 / 停止
- 不等待 A
- 调用方结果
- undefined
执行轨迹 / emit↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 开始返回一份受控 Promise;尚未完成
A:start - B 执行同步返回 0
B:0 - C 执行同步返回 'last'
C:last - 调用已返回结果为 undefined;不是 A 的 Promise
caller:undefined - A 完成实验放行后,Promise 解析为 undefined
A:end
调用返回 / 完成色块:派发端观察或跳过状态
- A 开始返回一份受控 Promise;尚未完成
A:start - B 执行同步返回 0
B:0 - C 执行同步返回 'last'
C:last - 调用已返回结果为 undefined;不是 A 的 Promise
caller:undefined - A 完成实验放行后,Promise 解析为 undefined
A:end
parallel正常结果
启动全部监听器,等 A 结束
B、C 的同步返回值不会成为派发结果。全部成功后,调用方等待到 undefined。
- 谁被调用
- A、B、C
- 等待 / 停止
- 全部 settled
- 调用方结果
- Promise<void>
执行轨迹 / parallel↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 开始返回一份受控 Promise;尚未完成
A:start - B 执行同步返回 0
B:0 - C 执行同步返回 'last'
C:last - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - A 完成实验放行后,Promise 解析为 undefined
A:end - 等待结束调用方 await 得到 undefined
caller:resolved:undefined
调用返回 / 完成色块:派发端观察或跳过状态
- A 开始返回一份受控 Promise;尚未完成
A:start - B 执行同步返回 0
B:0 - C 执行同步返回 'last'
C:last - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - A 完成实验放行后,Promise 解析为 undefined
A:end - 等待结束调用方 await 得到 undefined
caller:resolved:undefined
serial正常结果
A 完成后才进入 B,0 会截断
A 最终返回 undefined,因此继续。B 的 0 满足 isBailed;C 没有执行机会。
- 谁被调用
- A、B;跳过 C
- 等待 / 停止
- 逐个 await
- 调用方结果
- Promise → 0
执行轨迹 / serial↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 开始返回一份受控 Promise;尚未完成
A:start - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - A 完成实验放行后,Promise 解析为 undefined
A:end - B 执行同步返回 0
B:0 - 等待结束调用方 await 得到 0;C 未执行
caller:resolved:0
调用返回 / 完成色块:派发端观察或跳过状态
- A 开始返回一份受控 Promise;尚未完成
A:start - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - A 完成实验放行后,Promise 解析为 undefined
A:end - B 执行同步返回 0
B:0 - 等待结束调用方 await 得到 0;C 未执行
caller:resolved:0
bail正常结果
A 的 Promise 本身就是停止值
派发立即选中 A 返回的对象。它后来解析成 undefined,也不会让 B、C 重新加入。
- 谁被调用
- 只有 A
- 等待 / 停止
- 不等再判断
- 调用方结果
- A 的 Promise
执行轨迹 / bail↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 开始返回一份受控 Promise;尚未完成
A:start - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - A 完成实验放行后,Promise 解析为 undefined
A:end - 等待结束调用方 await 得到 undefined
caller:resolved:undefined
调用返回 / 完成色块:派发端观察或跳过状态
- A 开始返回一份受控 Promise;尚未完成
A:start - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - A 完成实验放行后,Promise 解析为 undefined
A:end - 等待结束调用方 await 得到 undefined
caller:resolved:undefined
waterfall正常结果
沿 next 向内调用,沿 return 向外返回
A、B、C 分别在 next 的结果后追加字母。终点返回 base,最外层拿到 baseCBA。
- 谁被调用
- A、B、C、inner
- 等待 / 停止
- 本组为同步链
- 调用方结果
- baseCBA
执行轨迹 / waterfall↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 进入调用 next(),控制权向内传递
A:enter - B 进入调用 next(),控制权向内传递
B:enter - C 进入调用 next(),控制权向内传递
C:enter - 进入终点 inner返回 'base'
inner:base - C 返回拿到内层结果,在末尾追加 C
C:exit - B 返回拿到内层结果,在末尾追加 B
B:exit - A 返回拿到内层结果,在末尾追加 A
A:exit - 调用已返回结果为 'baseCBA'
caller:baseCBA
调用返回 / 完成色块:派发端观察或跳过状态
- A 进入调用 next(),控制权向内传递
A:enter - B 进入调用 next(),控制权向内传递
B:enter - C 进入调用 next(),控制权向内传递
C:enter - 进入终点 inner返回 'base'
inner:base - C 返回拿到内层结果,在末尾追加 C
C:exit - B 返回拿到内层结果,在末尾追加 B
B:exit - A 返回拿到内层结果,在末尾追加 A
A:exit - 调用已返回结果为 'baseCBA'
caller:baseCBA
emitA 同步抛错
A 同步抛错,B、C 不执行
异常从 emit 调用处同步传播。广播并没有为每个监听器提供独立的错误隔离。
- 谁被调用
- 只有 A
- 等待 / 停止
- 当场中断
- 调用方结果
- throw Error
执行轨迹 / emit↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - 调用方取得 Error同步抛出或 Promise 拒绝,见本场景返回栏
caller:Error:A
调用返回 / 完成色块:派发端观察或跳过状态
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - 调用方取得 Error同步抛出或 Promise 拒绝,见本场景返回栏
caller:Error:A
parallelA 同步抛错
A 抛错后,B、C 仍会启动
async 包装将 A 的同步异常变为拒绝结果。等待全部 settled 后,派发拒绝为 AggregateError。
- 谁被调用
- A、B、C
- 等待 / 停止
- 全部 settled
- 调用方结果
- 拒绝 AggregateError
执行轨迹 / parallel↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - B 执行同步返回 0
B:0 - C 执行同步返回 'last'
C:last - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - 等待拒绝AggregateError.errors 含 A 的错误
caller:AggregateError:A
调用返回 / 完成色块:派发端观察或跳过状态
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - B 执行同步返回 0
B:0 - C 执行同步返回 'last'
C:last - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - 等待拒绝AggregateError.errors 含 A 的错误
caller:AggregateError:A
serialA 同步抛错
A 失败,派发 Promise 拒绝
A 的同步抛错使 serial 返回的 Promise 拒绝。后续监听器不会继续执行。
- 谁被调用
- 只有 A
- 等待 / 停止
- 首个失败即停
- 调用方结果
- 拒绝 Error
执行轨迹 / serial↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - 调用方取得 Error同步抛出或 Promise 拒绝,见本场景返回栏
caller:Error:A
调用返回 / 完成色块:派发端观察或跳过状态
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - 调用已返回 Promise此刻仅取得对象;是否继续由当前派发规则决定
caller:Promise - 调用方取得 Error同步抛出或 Promise 拒绝,见本场景返回栏
caller:Error:A
bailA 同步抛错
同步异常直接传给调用方
bail 没有 async 包装。A 抛错时,调用本身就抛错,B、C 不会被调用。
- 谁被调用
- 只有 A
- 等待 / 停止
- 当场中断
- 调用方结果
- throw Error
执行轨迹 / bail↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - 调用方取得 Error同步抛出或 Promise 拒绝,见本场景返回栏
caller:Error:A
调用返回 / 完成色块:派发端观察或跳过状态
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - 调用方取得 Error同步抛出或 Promise 拒绝,见本场景返回栏
caller:Error:A
waterfallA 同步抛错
A 没调用 next,链条止于 A
本场景在进入 A 时直接抛错,B、C 与 inner 均未运行。异常沿当前函数调用链向外传播。
- 谁被调用
- 只有 A
- 等待 / 停止
- 未进入 next
- 调用方结果
- throw Error
执行轨迹 / waterfall↓ 先后关系,非耗时比例
改用逐步轨迹查看返回时序图
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - 调用方取得 Error同步抛出或 Promise 拒绝,见本场景返回栏
caller:Error:A
调用返回 / 完成色块:派发端观察或跳过状态
- A 抛错直接 throw Error('A'),并非返回拒绝 Promise
A:throw - 调用方取得 Error同步抛出或 Promise 拒绝,见本场景返回栏
caller:Error:A