记得在 NodeJS 上继续使用回调和异步代码
Photo by 安东马克西莫夫 5642.su on 不飞溅
记得在 NodeJS 上继续使用回调和异步代码
一个简短的案例场景,通过记住 NodeJS 事件循环来提高应用程序性能。
我知道,在 2022 年,异步操作必须在 NodeJS 环境中受到青睐似乎很明显,但我将在本文中展示我如何重构代码以利用 NodeJS 的性能。 .
我假设仍在阅读本文的您已经熟悉 NodeJS 环境。确实,你可能是。但是,让我们做一些定义,以便更多人能够理解我将进一步说的话。
节点.js 是一个开源和跨平台的 JavaScript 运行时环境。它运行 V8 JavaScript 引擎(与 Google Chrome 相同),为该平台开发的应用程序在单个进程中运行,而不是为每个请求创建一个新线程。
这种单线程特性是 NodeJS 的核心概念,它在其标准库中提供了一组异步 I/O 原语,以防止 JavaScript 代码阻塞。但是怎么做呢?好吧,依靠一个定义明确的 事件循环 , 注册不时运行的函数,允许处理许多请求(一次一个)。
总结一下,在这种环境下,您的应用程序是单线程的,您应该将每个请求作为一组可以暂停和恢复的指令来处理,以便您能够尽可能地处理大多数请求。在为 NodeJS 编写应用程序时,这一定是一般的想法。
好吧,我认为现在是时候展示我一开始承诺的真实场景了。所以,让我们去做吧。
我有一个在 NodeJS 平台上运行的应用程序。它与第三方 API 集成工作,从中定期获取一些数据并将其保存在关系数据库中。必须更新已持久化的注册表,否则应创建新的注册表。到目前为止,一切都很好,但我们有一些限制:
- API 仅列出所有数据(没有任何类型的过滤)
- 数据是分页的(当然),但你事先并不知道,所以你只知道在读取服务器响应时到达了最后一页。
牢记这些条件,我发现第一个实现类似于下面的代码:
First implementation
上面的代码正是需要的。它从第三方 API 服务器获取数据并将它们附加到一个列表中,利用最后的分页结果重复它(由 页面令牌
) 被发现。但是,它有一些缺陷:
- 它只允许处理数据(由
结果列表
) 获取所有页面后。 - 这
做...同时
循环可能需要更长的时间才能完成,因此事件循环被此操作阻塞(请记住: 不要阻塞事件循环 )。
这些是我考虑的要点,以便以仍然可靠的方式重构此代码,但将其提高到应用程序范围内的性能。过了一会儿,我提出的最终解决方案是:
Second implementation
最终的代码比前一个复杂一点(只是一点点),但值得努力去理解它。让我们看看为什么。
首先, 全部列出
两个实现中的函数都返回一个 Promise 对象。第一个隐式使用 异步
关键字,第二个显式创建一个承诺实例。但是,第二种实现也需要一个参数 流内
那一定是 可读流 .
你不知道什么是流?不好了!让我看看……我们可以将流定义为允许您通过 NodeJS 应用程序异步发送数据的接口。抽象出细节。试想一下,您可以在应用程序的一个部分发送一部分数据,而这些数据可以从另一部分读取。这是基本的想法。
输入流实例允许我们在这部分代码上使用异步处理。
第 26 行第一次调用 获取API数据
该方法将执行 HTTP 请求并从第三方 API 服务器获取部分数据。第 27 行注册一个回调以获取接收到的响应并将其转发给 过程响应
函数,以及输入流。
第 10-21 行描述了简单地将数据列表转发到流实例的数据处理,如果还有另一个页面,则在另一个页面之后递归调用自身 获取API数据
调用。
通过流推送的即时数据列表(第 12 行) 允许应用程序完全处理 API 数据 一经请求 ,根据接收的顺序,无需等待处理大量数据和 既不将它们附加到列表中 (这可以减少内存消耗)。此外,我们与 NodeJS 事件循环 无阻塞的想法,一旦我们的请求被(简短的)回调执行处理,可以在几个期间调用和恢复 事件循环 .
因此,在最后一个实现中,我们修复了第一个代码片段中指出的缺陷。现在应用程序获得了性能改进。对我们所有人来说都是伟大的工作! 😃
好吧,我希望你能做到这一点。这并不难,是吗?当然,我试图简化这篇文章的一些内容,并抽象了许多细节,但我提供了一些链接,以防你想了解更多关于它们的信息。
我可能会随机返回另一个文本,但在此之前,感谢您的阅读。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明