嗯,首先,在我看来,正如所描述的,这个函数调用会以某种方式阻塞调用进程,直到所有指定的事件都发生——当然这在 JavaScript 中是不合理的。
因此,首先,我认为您的函数应该需要一个回调,作为它的唯一参数,当一切最终发生时,该回调将被调用。
现在 - 关于“如何优雅地处理步骤 1、2 和 3” ...立即想到的是 有限状态机 (FSM) 的概念 算法。
假设您的函数调用导致一个新的“请求”被放置在某个请求表队列中,并且,如果需要,一个计时器请求(设置为在 1 毫秒内关闭)为该队列提供服务。 (除其他外,该条目将包含对您的回调的引用。)我们还假设该请求被赋予了一个随机字符串“nonce”,它将用于唯一标识它:这将传递给各种外部请求和必须包含在他们的相应回复中。
FSM的想法是请求会有一个状态,(属性),比如:DOWNLOADING_FROM_B,B_DOWNLOADS_COMPLETE 、DOWNLOADING_FROM_C、C_REQUESTS_COMPLETE 等等。这样,每个将在这个完全异步过程中发挥作用的回调将 (1) 能够通过其随机数定位请求条目,然后 (2) em> 仅基于对条目的state 的检查,明确地“知道下一步该做什么”和“要分配什么新状态(如果有)”。
例如,当状态达到C_REQUESTS_COMPLETE 时,就应该调用您最初提供的回调,并删除请求表条目。
您可以轻松地绘制出在任意复杂场景中可能发生的所有“状态转换”(哪些状态可以导致哪些状态,以及当它们发生时要做什么),无论您是否真的创建了一个数据结构来表示所谓的“状态表”,尽管有时这样做会更加优雅(!)。 (可能是混乱的决策逻辑被简单地推到一个简单的表查找中。)
当然,这是一种经典算法,适用于——并且已经被用于——“太阳下的每一种编程语言”。 (很多硬件设备也使用它。)