异步流控制

JavaScript 控制流就是回调处理。 以下是帮助你开发的策略。

目录
请记住,此内容仅供参考,可能很快就会过时。 我们推荐其他来源,例如 MDN

这篇文章中的材料很大程度上受到了 Mixu 的 Node.js 书籍 的启发。

就其核心而言,JavaScript 被设计为在 "主" 线程上是非阻塞的,这是渲染视图的地方。 你可以想象这在浏览器中的重要性。 当主线程被阻塞时,它会导致终端用户害怕的臭名昭著的 "卡住",并且无法调度其他事件,例如导致数据采集丢失。

这会产生一些独特的约束,只有函数式编程风格才能解决。 这就是回调的用武之地。

但是,在更复杂的过程中处理回调可能变得具有挑战性。 这通常会导致 "回调地狱",其中带有回调的多个嵌套函数使代码更难阅读、调试、组织等。

当然,在现实生活中很可能会有额外的代码行来处理 result1result2 等,因此,这个问题的长度和复杂性通常会导致代码看起来比上面的例子更乱。

这就是函数发挥重要作用的地方。 更复杂的操作由许多函数组成:

  1. 启动器风格/输入
  2. 中间件
  3. 终止符

"启动器风格/输入" 是序列中的第一个函数。 此函数将接受原始输入(如果有)以进行操作。 该操作是一系列可执行的函数,原始输入主要是:

  1. 全局环境中的变量
  2. 有或没有参数的直接调用
  3. 通过文件系统或网络请求获得的值

网络请求可以是由外部网络、同一网络上的另一个应用或应用本身在同一网络或外部网络上发起的传入请求。

中间件函数将返回另一个函数,终止函数将调用回调。 下面说明了网络或文件系统请求的流程。 这里的延迟为 0,因为所有这些值都在内存中可用。

状态管理

函数可能依赖于状态,也可能不依赖于状态。 当函数的输入或其他变量依赖于外部函数时,就会出现状态依赖。

这样,状态管理有两种主要策略:

  1. 将变量直接传递给函数,并且
  2. 从缓存、会话、文件、数据库、网络或其他外部源获取变量值。

注意,我没有提到全局变量。 使用全局变量管理状态通常是一种草率的反模式,这使得保证状态变得困难或不可能。 应尽可能避免复杂程序中的全局变量。

控制流

如果对象在内存中可用,则可以进行迭代,并且控制流不会发生变化:

但是,如果数据存在于内存之外,迭代将不再有效:

为什么会这样? setTimeout 指示 CPU 将指令存储在总线上的其他位置,并指示数据被安排在稍后的时间拾取。 在函数再次到达 0 毫秒标记之前经过了数千个 CPU 周期,CPU 从总线获取指令并执行它们。 唯一的问题是歌曲 ('') 在数千个循环之前被返回。

在处理文件系统和网络请求时也会出现同样的情况。 主线程不能被阻塞一段不确定的时间 - 因此,我们使用回调以可控的方式及时安排代码的执行。

你将能够使用以下 3 种模式执行几乎所有操作:

  1. 在系列中: 函数将按照严格的顺序执行,这与 for 循环最相似。

  2. 全并行: 当顺序不是问题时,例如通过电子邮件发送 1,000,000 个电子邮件收件人的列表。

  3. 有限并行: 带限制的并行,例如成功向 10E7 用户列表中的 1,000,000 个收件人发送电子邮件。

每个都有自己的用例、好处和问题,你可以尝试并更详细地阅读。 最重要的是,请记住模块化你的操作并使用回调! 如果你有任何疑问,请将所有内容都视为中间件!

Node.js 中文网 - 粤ICP备13048890号