使用nodejs解决各种各样的问题(开发人员常犯的)
使用nodejs解决各种各样的问题(开发人员常犯的)
2024-07-01 12:16:00  作者:扭曲的灵魂  网址:https://m.xinb2b.cn/know/wxg343904.html

自从 Node.js 面世以来,它就受到了相当多的赞扬和批评。辩论仍在继续,可能不会很快结束。在这些辩论中,我们经常忽略的是,每种编程语言和平台都会基于某些问题受到批评,这些问题是由我们使用平台的方式造成的。

不管 Node.js 让编写安全代码多么困难,以及编写高并发代码多么容易,该平台已经存在了很长一段时间,并已被用于构建大量强大而复杂的 Web 服务。这些 Web 服务可以很好地扩展,并通过它们在 Internet 上的持久性证明了它们的稳定性。

但是,与任何其他平台一样,Node.js 容易受到开发人员问题的影响。其中一些错误会降低性能,而另一些错误会使 Node.js 看起来无法用于您想要实现的任何目标。在本文中,我们将看看 Node.js 新手经常犯的十个常见错误,以及如何避免这些错误成为 Node.js 专业人士。

错误 #1:阻塞事件循环

Node.js 中的 JavaScript(就像在浏览器中一样)提供了单线程环境。这意味着您的应用程序没有两个部分是并行运行的。相反,并发是通过异步处理 I/O 绑定操作来实现的。例如,从 Node.js 到数据库引擎的请求以获取一些文档是允许 Node.js 专注于应用程序的其他部分的原因:

使用nodejs解决各种各样的问题(开发人员常犯的)(1)

使用nodejs解决各种各样的问题(开发人员常犯的)(2)

然而,在连接了数千个客户端的 Node.js 实例中,一段受 CPU 限制的代码就足以阻止事件循环,让所有客户端等待。受 CPU 限制的代码包括尝试对大型数组进行排序、运行极长的循环等等。例如:

使用nodejs解决各种各样的问题(开发人员常犯的)(3)

如果在一个小的“users”数组上运行,调用这个“sortUsersByAge”函数可能没问题,但是对于一个大数组,它会对整体性能产生可怕的影响。如果这是绝对必须完成的事情,并且您确定在事件循环中不会有任何其他等待(例如,如果这是您使用 Node.js 构建的命令行工具的一部分,并且它如果整个事情同步运行都没有关系),那么这可能不是问题。但是,在尝试一次为数千名用户提供服务的 Node.js 服务器实例中,这种模式可能是致命的。

如果从数据库中检索此用户数组,理想的解决方案是直接从数据库中获取已排序的用户。如果事件循环被编写用于计算长期金融交易数据历史总和的循环阻塞,则可以将其推迟到某些外部工作者/队列设置,以避免占用事件循环。

如您所见,对于此类 Node.js 问题没有灵丹妙药的解决方案,而是需要单独解决每种情况。基本思想是不在前端的 Node.js 实例中进行 CPU 密集型工作——客户端同时连接的那些。

错误 #2:多次调用回调

JavaScript 一直依赖回调。在 Web 浏览器中,事件是通过传递对(通常是匿名的)函数的引用来处理的,这些函数的作用类似于回调。在 Node.js 中,回调曾经是代码中异步元素相互通信的唯一方式——直到引入了 Promise。回调仍在使用中,包开发人员仍然围绕回调设计他们的 API。与使用回调相关的一个常见 Node.js 问题是多次调用它们。通常,包提供的用于异步执行某些操作的函数被设计为期望函数作为其最后一个参数,该参数在异步任务完成时调用:

使用nodejs解决各种各样的问题(开发人员常犯的)(4)

注意每次调用“done”时都有一个返回语句,直到最后一次。这是因为调用回调不会自动结束当前函数的执行。如果第一个“return”被注释掉,传递一个非字符串密码给这个函数仍然会导致“computeHash”被调用。根据“computeHash”如何处理这种情况,“done”可能会被多次调用。当他们传递的回调被多次调用时,从其他地方使用此函数的任何人都可能完全措手不及。

小心是避免此 Node.js 错误所需要的一切。一些 Node.js 开发人员习惯于在每次回调调用之前添加一个 return 关键字:

使用nodejs解决各种各样的问题(开发人员常犯的)(5)

在很多异步函数中,返回值几乎没有任何意义,所以这种方法往往可以很容易地避免这样的问题。

错误 #3:深度嵌套回调

深度嵌套的回调,通常被称为“回调地狱”,它本身并不是 Node.js 的问题。但是,这可能会导致代码快速失控的问题:

使用nodejs解决各种各样的问题(开发人员常犯的)(6)

使用nodejs解决各种各样的问题(开发人员常犯的)(7)

任务越复杂,情况就越糟糕。通过以这种方式嵌套回调,我们很容易以容易出错、难以阅读和难以维护的代码告终。一种解决方法是将这些任务声明为小函数,然后将它们链接起来。虽然,(可以说)最干净的解决方案之一是使用处理异步 JavaScript 模式的实用程序 Node.js 包,例如Async.js:

使用nodejs解决各种各样的问题(开发人员常犯的)(8)

与“async.waterfall”类似,Async.js 还提供了许多其他函数来处理不同的异步模式。为简洁起见,我们在这里使用了更简单的示例,但实际情况往往更糟。

错误 #4:期望回调同步运行

带有回调的异步编程可能不是 JavaScript 和 Node.js 独有的东西,但它们是其流行的原因。对于其他编程语言,我们习惯于可预测的执行顺序,两条语句将一个接一个地执行,除非有特定的指令在语句之间跳转。即使这样,这些通常也仅限于条件语句、循环语句和函数调用。

但是,在 JavaScript 中,使用回调,特定函数可能无法正常运行,直到它等待的任务完成。当前函数的执行将一直运行到最后,没有任何停止:

使用nodejs解决各种各样的问题(开发人员常犯的)(9)

您会注意到,调用“testTimeout”函数将首先打印“Begin”,然后打印“Waiting..”,然后是“Done!”消息。大约一秒钟后。

触发回调后需要发生的任何事情都需要从其中调用。

错误#5:分配给“exports”,而不是“module.exports”

Node.js 将每个文件视为一个小的独立模块。如果你的包有两个文件,可能是“a.js”和“b.js”,那么为了让“b.js”访问“a.js”的功能,“a.js”必须通过添加属性来导出它出口对象:

使用nodejs解决各种各样的问题(开发人员常犯的)(10)

完成后,任何需要“a.js”的人都将获得一个具有属性函数“verifyPassword”的对象:

使用nodejs解决各种各样的问题(开发人员常犯的)(11)

但是,如果我们想直接导出这个函数,而不是作为某个对象的属性呢?我们可以覆盖导出来执行此操作,但我们不能将其视为全局变量:

使用nodejs解决各种各样的问题(开发人员常犯的)(12)

请注意我们如何将“导出”视为模块对象的属性。这里“module.exports”和“exports”之间的区别非常重要,并且经常是新 Node.js 开发人员感到沮丧的原因。

错误 #6:从内部回调中抛出错误

JavaScript 有异常的概念。模仿几乎所有支持异常处理的传统语言的语法,例如 Java 和 C ,JavaScript 可以在 try-catch 块中“抛出”和捕获异常:

使用nodejs解决各种各样的问题(开发人员常犯的)(13)

但是,try-catch 在异步情况下不会像您期望的那样运行。例如,如果你想用一个大的 try-catch 块来保护一大块具有大量异步活动的代码,它不一定有效:

使用nodejs解决各种各样的问题(开发人员常犯的)(14)

如果对“db.User.get”的回调异步触发,那么包含 try-catch 块的作用域早就脱离了上下文,它仍然能够捕获从回调内部抛出的错误。

这就是在 Node.js 中以不同方式处理错误的方式,这使得在所有回调函数参数上遵循 (err, ...) 模式至关重要——如果发生错误,所有回调的第一个参数都应该是一个错误.

错误 #7:假设 Number 是整数数据类型

JavaScript 中的数字是浮点数——没有整数数据类型。您不会认为这是一个问题,因为不会经常遇到大到足以强调浮动限制的数字。这正是与此相关的错误发生的时候。由于浮点数只能将整数表示形式保存到某个值,因此在任何计算中超过该值都会立即开始搞砸。尽管看起来很奇怪,但以下在 Node.js 中的计算结果为 true:

使用nodejs解决各种各样的问题(开发人员常犯的)(15)

不幸的是,JavaScript 中数字的怪癖并没有就此结束。即使数字是浮点数,也适用于整数数据类型的运算符:

使用nodejs解决各种各样的问题(开发人员常犯的)(16)

然而,与算术运算符不同的是,位运算符和移位运算符仅适用于此类大“整数”数字的尾随 32 位。例如,尝试将“Math.pow(2, 53)”移动 1 将始终计算为 0。尝试对相同的大数进行按位或 1 将计算为 1。

使用nodejs解决各种各样的问题(开发人员常犯的)(17)

您可能很少需要处理大数,但如果您这样做,有很多大整数库可以实现对大精度数的重要数学运算,例如node-bigint。

错误 #8:忽略流式 API 的优势

假设我们想要构建一个类似代理的小型 Web 服务器,通过从另一个 Web 服务器获取内容来响应请求。例如,我们将构建一个服务 Gravatar 图像的小型 Web 服务器:

使用nodejs解决各种各样的问题(开发人员常犯的)(18)

在这个 Node.js 问题的特定示例中,我们从 Gravatar 获取图像,将其读入缓冲区,然后响应请求。考虑到 Gravatar 图像不是太大,这并不是一件坏事。但是,想象一下,如果我们代理的内容大小是数千兆字节。更好的方法是:

使用nodejs解决各种各样的问题(开发人员常犯的)(19)

在这里,我们获取图像并简单地将响应传递给客户端。在任何时候我们都不需要在提供之前将整个内容读入缓冲区。

错误 #9:使用 Console.log 进行调试

在 Node.js 中,“console.log”允许您将几乎所有内容打印到控制台。将对象传递给它,它会将其打印为 JavaScript 对象字面量。它接受任意数量的参数,并以空格分隔的方式打印它们。开发人员可能会想用它来调试他的代码有很多原因;但是,强烈建议您在实际代码中避免使用“console.log”。您应该避免在整个代码中编写“console.log”来调试它,然后在不再需要它们时将它们注释掉。相反,请使用专门为此构建的令人惊叹的库之一,例如debug。

此类软件包提供了在启动应用程序时启用和禁用某些调试行的便捷方法。例如,使用调试,可以通过不设置 DEBUG 环境变量来防止任何调试行被打印到终端。使用它很简单:

使用nodejs解决各种各样的问题(开发人员常犯的)(20)

要启用调试行,只需在环境变量 DEBUG 设置为“app”或“*”的情况下运行此代码:

使用nodejs解决各种各样的问题(开发人员常犯的)(21)

使用nodejs解决各种各样的问题(开发人员常犯的)(22)

  • 艾米丽身高(艾米丽简介)
  • 2024-07-01艾米丽简介艾米丽·西姆博(EmilySeebohm),女,1992年6月5日出生于澳大利亚身高180厘米,体重70kg,澳大利亚游泳运动员当艾米丽-西姆博14岁那年打破澳大利亚女子100米仰泳纪录的时候,她就已。
  • 神车冒火(竟然还有人点火中通神车)
  • 2024-07-01竟然还有人点火中通神车周末的可转债新政,对于可转债板块的打击效果非常明显,资金争相出逃成交量直接跌到1200亿,过几天热度继续下降,从高位2000亿腰斩到千亿以下也是有可能的创业板成为最大受益者全场20厘米涨停共8只,2连。
  • 何姓的起源及由来(百家姓起源之何姓)
  • 2024-07-01百家姓起源之何姓何姓的起源主要分为以下三种:第一种,就是出自姬姓,是周文王的后人周文王的儿子周成王第唐叔虞的后人韩王安被秦灭掉之后,便带着家眷逃亡到了现在的江淮一带,改姓为何,其子孙也开始以何为姓第二种,在隋唐时期我。
  • 通货膨胀多可怕(通货膨胀有多可怕)
  • 2024-07-01通货膨胀有多可怕结果非但没有达成想要的效果,反而使国内物价飞涨,国内通货膨胀率曾一度飙升到200000%这应该是史上最大无语的政府了吧?从今年年初开始,美股一直在下跌,结束了美股十多年的长牛行情,导致全球的股市都是惨。
  • 乔恩费儒情景喜剧(乔恩费儒打造了钢铁侠的男人)
  • 2024-07-01乔恩费儒打造了钢铁侠的男人时光网特稿今年夏天,好莱坞最忙的人中,一定有乔恩·费儒的身影现在正在大银幕上公映的《蜘蛛侠:英雄远征》中,乔恩再次出演了托尼·史塔克的司机“哈皮霍根”,还跟小蜘蛛的梅姨产生了些情愫;乔恩执导的迪士尼新。
  • 龙岭迷窟高伟光有多少戏份(龙岭迷窟高伟光上线)
  • 2024-07-01龙岭迷窟高伟光上线自4月1日开始,《龙岭迷窟》已上线热播一周有余豆瓣评分稳定在8.2,没有下滑趋势故事节奏快,喜剧感与惊险感并存场景恢宏,镜头调度和音乐都是电影级别,强势成为有史以来最佳鬼吹灯作品前六集中,胡八一、王胖。
  • 诸城烧肉的做法(你学会了吗)
  • 2024-07-01你学会了吗选材原材料主要是猪头(包括猪耳朵、口条)、猪蹄和猪肚、猪大肠、心、肝、肺,也可以用猪尾巴看各人的喜好先在大铁盆里清洗干净猪头、猪蹄要一点一点拔净残毛,内脏要翻过来清洗,猪大肠清洗最费事,需要一点点用粗。
  • 表达思念的唯美的句子(表达思念的句子简短)
  • 2024-07-01表达思念的句子简短1、阳春三月,将满天飞舞的思绪,凝成思念;将满园关不住的春色,写上眉端;将五彩斑斓的美艳,收于祝愿,带去来自远方的问候——送给永远开心的你2、总有起风的清晨,总有温暖的午后,总有绚烂的黄昏,总有流星的。
  • vim的三个功能(学好vim一篇就够了-vi和vim的使用教程)
  • 2024-07-01学好vim一篇就够了-vi和vim的使用教程它是一个老式的文字处理工具,但是功能很齐全,不仅是文本处理工具,还是一个程序编辑工具,就连官方网站也说vim是一个程序开发工具而不是文字处理软件,因为它包含了很多额外的功能,如:多文件编辑,区块复制等。
  • mate(30支持双微信吗(你知道吗)
  • 2024-07-01你知道吗mate30支持双微信首先进入华为mate30的手机桌面,点击打开桌面上的【设置】在设置页面找到并点击【应用】选项进入应用页面后,点击选择【应用分身】选项卡点击【微信】右侧的开关,显示已经分身即可。
  • 超级好看的植物简笔画(上百种植物花草的简笔画素材)
  • 2024-07-01上百种植物花草的简笔画素材上百种花草植物的画法,点亮你的手账和手抄报,马住学~盆栽简笔画素材盆栽简笔画大全植物简笔画大全简笔画图片大全植物简笔画图片大全简笔画大全手帐素材花简笔画大全叶子简笔画大全,。