NodeJS 开发者的 10 个常见错误

512 查看

自 Node.js 公诸于世的那一刻,就伴随着赞扬和批评的声音。这个争论仍在持续,而且并不会很快消失。而我们常常忽略掉这些争论产生的原因,每种编程语言和平台都是因某些问题而受到批评,而这些问题的产生,是取决于我们如何使用这个平台。不管有多难才能写出安全的 Node.js 代码,或有多容易写出高并发的代码,该平台已经有相当长一段时间,并已被用来建立一个数量庞大、稳健和成熟的 web 服务器。这些 web 服务器伸缩性强,并且它们通过在 Internet 上稳定的运行时间,证明自己的稳定性。

然而,像其它平台一样,Node.js 容易因开发者问题而受到批评。一些错误会降低性能,而其它一些问题会让 Node.js 直接崩溃。在这篇文章里,我们将会聊一聊关于 Node.js 新手的 10 个常犯错误,并让他们知道如何避免这些错误,从而成为一名 Node.js 高手。

错误 #1:阻塞事件循环

JavaScript 在 Node.js (就像在浏览器一样) 提供单线程执行环境。这意味着你的程序不能同时执行两部分代码,但能通过 I/O 绑定异步回调函数实现并发。例如:一个来自Node.js 的请求是到数据库引擎获取一些文档,在这同时允许 Node.js 专注于应用程序其它部分:

然而,具有计算密集型代码的 Node.js 实例被数以万计客户端同时连接执行时,会导致阻塞事件循环,并使所有客户端处于等待响应状态。计算密集型代码,包括尝试给一个庞大数组进行排序操作和运行一个格外长的循环等。例如:

基于小 “users” 数组执行 “sortUserByAge” 函数,可能没什么问题,当基于庞大数组时,会严重影响整体性能。如果在不得不这样操作的情况下,你必须确保程序除了等待事件循环而别无他事(例如,用 Node.js 建立命令行工具的一部分,整个东西同步运行是没问题的),然后这可能没问题。然而,在 Node.js 服务器实例尝试同时服务成千上万个用户的情况下,这将是一个毁灭性的问题。

如果用户数组是从数据库检索出来的,有个解决办法是,先在数据库中排序,然后再直接检索。如果因需要计算庞大的金融交易历史数据总和,而造成阻塞事件循环,这可以创建额外的worker / queue 来避免阻塞事件循环。

正如你所看到的,这没有新技术来解决这类 Node.js 问题,而每种情况都需要单独处理。而基本解决思路是:不要让 Node.js 实例的主线程执行 CPU 密集型工作 – 客户端同时链接时。

错误 #2:调用回调函数多于一次

JavaScript 一直都是依赖于回调函数。在浏览器中,处理事件是通过调用函数(通常是匿名的),这个动作如同回调函数。Node.js 在引进 promises 之前,回调函数是异步元素用来互相连接对方的唯一方式 。现在回调函数仍被使用,并且包开发者仍然围绕着回调函数设计 APIs。一个关于使用回调函数的常见 Node.js 问题是:不止一次调用。通常情况下,一个包提供一个函数去异步处理一些东西,设计出来是期待有一个函数作为最后一个参数,当异步任务完成时就会被调用:

注意每次调用 “done” 都有一个返回语句(return),而最后一个 “done” 则可省略返回语句。这是因为调用回调函数后,并不会自动结束当前执行函数。如果第一个 “return” 注释掉,然后给这个函数传进一个非字符串密码,导致 “computeHash” 仍然会被调用。这取决于 “computeHash” 如何处理这样一种情况,“done” 可能会调用多次。任何一个人在别处使用这个函数可能会变得措手不及,因为它们传进的该回调函数被多次调用。

只要小心就可以避免这个 Node.js 错误。而一些 Node.js 开发者养成一个习惯是:在每个回调函数调用前添加一个 return 关键字。

对于许多异步函数,它的返回值几乎是无意义的,所以该方法能让你很好地避免这个问题。

错误 #3:函数嵌套过深

函数嵌套过深,时常被称为“回调函数地狱”,但这并不是 Node.js 自身问题。然而,这会导致一个问题:代码很快失去控制。