彩票走势图

想成为更好的 Node开发人员?你需要知道这10个技巧

转帖|行业资讯|编辑:龚雪|2017-03-01 11:34:33.000|阅读 150 次

概述:在这篇中,笔者会列出 2017 年成为更好 Node 开发者的技巧的大纲。这些技巧一部分是在具体实践中总结得出的,一部分借鉴了 Node 和 npm 优秀模块开发者的经验。

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

注意: 这篇文章之前的标题是 “来自平台大神的最佳实践分享”。文章内容是经过实际的测试和试验写出,但并非 2017 年最新技巧。 虽然,Node 大神分享的最佳经典实践在 2017 年,2018 年甚至 2019 年都会受用,但一些尖端功能,像 async/await, promises 并没有涵盖在内。因为这些新特性不在 Node 核心代码中,也不如 npm 和 Express 流行。文章第二部分,我将介绍此文章的性质。

我开始作为全职Node开发是在2012年,当我加入了Storify公司。 从那时起,我从没有回头或者觉得挂念Python,Ruby,Java和PHP——这些贯穿我之前十年web开发工作的语言。

Storify对我来说是一份有趣的工作,因为不像大多数公司, Storify所有的项目运行(也许今后依旧)都是使用Javascript。你看,大多数公司,尤其是大公司如贝宝(PayPal)、沃尔玛(Walmart)、或第一资本(Capital One),只是使用Node作为他们堆栈的某部分。通常他们使用它作为API途径或一个业务流程层。这也是不错的,但是对于一个软件工程师来说,没有什么比完全沉浸在一个Node环境中更棒的了。

我这篇博客中,我会列出 2017 年成为更好 Node 开发者的技巧的大纲。这些技巧一部分是我在具体实践中总结得出的,一部分借鉴了 Node 和 npm 优秀模块开发者的经验。主要内容如下:

下面,让我们对每项内容都进行一下了解吧~

避免复杂性

npm 的作者 Isaac Z. Schlueter 写了一些模板,我们可以看下。例如, 用  在模块中强制实施 JavaScript 严格模式,只需要三行代码:

var module = require('module') module.wrapper[0] += '"use strict";' Object.freeze(module.wrap) 

那么,为什么要避免复杂性呢? 美国海军传说中,有一句很著名的话:化繁为简,返璞归真(或理解为“编码的方式简单点,傻蛋!”)事实证明,人类大脑一次只能记住 5 项至 7项的内容,这就是此处要求简单的原因。

缩小代码模块,有利于你和开发者更好地理解代码,你也能更好地进行测试。参考以下示例:

app.use(function(req, res, next) { if (req.session.admin === true) return next() else return next(new Error('Not authorized')) }, function(req, res, next) { req.db = db next() })

或如下代码:

const auth = require('./middleware/auth.js') const db = require('./middleware/db.js')(db) app.use(auth, db)

我相信大多数的读者都更喜欢第二个示例,尤其是在名称可以自解释时。当然,在你写代码时,你能理解它的运行方式。或许,你还会为能将如此多的方法用在一行代码中而沾沾自喜。但是,代码不会说话啊。如果你把代码写的复杂而严谨,当你时隔六个月再来看,或者某天你睡迷糊了或喝醉了来看,理解起它们来会非常困难,更不要说根本不了解其算法和复杂性的同事了。保持简单,这一准则在使用 Node 异步方式的时候特别受用。

有一种 ,不过它只影响了依赖公共注册表的项目,并在 11 分钟之后重新发布。最小化所带来的益处远大于其缺点。而且,npm 已经,任何重要的项目都应该使用缓存或私有注册中心(作为临时解决方案)。

使用异步代码

同步代码确实在 Node 中有一个(低的)位置。 它主要用于编写 CLI 命令或与 Web 应用程序无关的其他脚本。Node 开发者主要构建 Web 应用程序,因此他们使用异步代码,以避免阻塞线程。

例如,这可能是可行的,如果我们只是建立一个数据库脚本,而不是一个系统来处理并行/并发任务:

let data = fs.readFileSync('./acconts.json') db.collection('accounts').insert(data, (results))=>{ fs.writeFileSync('./accountIDs.json', results, ()=>) })

但当建立一个Web应用程序时,这样写会更好:

app.use('/seed/:name', (req, res) => { let data = fs.readFile(`./$.json`, ()=>{ db.collection(req.params.name).insert(data, (results))=>{ fs.writeFile(`./$IDs.json`, results, ()=) }) }) })

区别就在于你是写并发系统(长期运行)还是非并发系统(短期运行)。根据实践经验,我们通常在 Node 中使用异步代码。

避免阻塞请求

Node 有个简单的模板加载系统,它使用的是 CommonJS 模板规范。它内置的 require 函数是将单独存放的模板包含进来的简易方式。不像 AMD/requirejs,Node/CommonJS 的模板加载方式是同步的。require 的工作原理:导入在模板或文件中导出的内容。

const react = require('react')

大多数开发者都不知道 require 有缓存。因此,只要解析的域名没有变化(在 nmp 模板中是没有的), 模块中的代码会只执行一次并将结果保存在一个变量中(同一进程内)。这是一个很不错的优化。然而,即使在缓存的情况下,你也最好把 require 语句放在前面。 看看下面的代码,在真正进入路由的时候才加载 axios 模块。/connect 路由出乎预料的慢,因为它在导入模块的时候才开始请求文件:

app.post('/connect', (req, res) => { const axios = require('axios') axios.post('/api/authorize', req.body.auth) .then((response)=>res.send(response)) })

更好更高效的方式是服务器启动后就加载模块,而不是在路由中:

const axios = require('axios') const express = require('express') app = express() app.post('/connect', (req, res) => { axios.post('/api/authorize', req.body.auth) .then((response)=>res.send(response)) })

了解 require 可被缓存

我在上面提到过 require 可缓存,但有趣的是我们可以在 module.exports 外部进行编码,比如:

console.log('I will not be cached and only run once, the first time') module.exports = () => { console.log('I will be cached and will run every time this module is invoked') }

知道有些代码只运行一次,你可以将这一特点作为优势。

时刻检查错误

Node 不是 Java,在 Java 中,你可以抛出错误,因为大多数时候,当你发现错误时,你会中止应用程序的运行。并且,在 Java 中,你可以通过单独的 try...catch 处理多个错误。

但 Node 不是这样。因为 Node 使用的是事件循环和异步执行,在错误发生时,任何错误都与错误处理程序的上下文分离(比如 try...catch)。下述代码在 Node 中无效:

try { request.get('/accounts', (error, response)=>{ data = JSON.parse(response) }) } catch(error) { // Will NOT be called console.error(error) }

但 try...catch 也可在 Node 同步代码中使用。因此,这是重构前面代码段的更好的方式:

request.get('/accounts', (error, response)=>{ try { data = JSON.parse(response) } catch(error) { // Will be called console.error(error) } })

如果我们不能将 request 调用放在 try...catch 块中,我们就不能处理来自 request 的错误。Node 开发者采用提供包含 error 参数的回调来解决这个问题。这样你需要在每个回调中手工处理错误。你需要检查 error(确保它不是 null),然后将相应的错误消息显示给用户或者客户端,并记录下来。也可以通过调用栈中的 callback 往回传(如果你有回调,而且调用栈上还有另一个函数)。

request.get('/accounts', (error, response)=>{ if (error) return console.error(error) try { data = JSON.parse(response) } catch(error) { console.error(error) } })

你还可以使用 库。 你可以使用以下代码来避免在无数回调中出现手动检查的误差。 (Hello, ).

var ok = require('okay') request.get('/accounts', ok(console.error, (response)=>{ try { data = JSON.parse(response) } catch(error) { console.error(error) } }))

返回回调或使用 if … else

Node 是并发的。因此它有个特点就是,如果不加以注意,就会出现 bug。安全起见,我们使用 return 语句终止执行:

let error = true if (error) return callback(error) console.log('I will never run - good.')

避免由于错误的控制流导致的一些无意的并发(和失败操作)。

let error = true if (error) callback(error) console.log('I will run. Not good!')

确保返回一个回调,以防止继续执行。

监听错误事件

几乎所有的 Node 类/对象都扩展了事件发射器(观察者模式)并发出错误事件。 在错位被破坏之前,这给开发人员提供了捕获错误并处理的机会。

养成使用 .on() 为错误创建事件侦听器的好习惯

var req = http.request(options, (res) => { if (('' + res.statusCode).match(/^2\d\d$/)) { // Success, process response } else if (('' + res.statusCode).match(/^5\d\d$/)) // Server error, not the same as req error. Req was ok. } }) req.on('error', (error) => { // Can't even make a request: general error, e.g. ECONNRESET, ECONNREFUSED, HPE_INVALID_VERSION console.log(error) })

了解 npm

很多 Node 开发者和前端开发者都知道—— save(npm install 参数)可以安装一个模板,但要在 package.json 记录模板的版本。当然,还有 save-dev, 用于在 devDependencies 添加记录 (记录生产中不需要的模板)。但你知道用 -S 和 -D 代替 --save 和 --save-dev 吗?你不妨试试。

在安装模块的时候,去删除 -S  和 -D 为你添加的那些 ^ 记号。它们非常危险,因为它们允许 npm install(或简写为 npm i)从 npm 库中拉取最新的小版本(语义化的版本号中的第2个数)。比如从 v6.1.0 到 v6.2.0 就是一个小版本发布。

npm 团队信任 ,但你不能。他们加上 ^ 符号是因为他们相信开源作者不会在小版本中引入破坏性的修改。然而明眼人都知道它是不可靠的。你应该锁定版本号,最好使用 shrinkwrap:npm shrinkwrap 创建一个包含依赖的具体版本的新文件。

结语

这篇博客只是第一部分,其中已经涵盖了很多内容,从回调函数和异步代码的使用,到错误的检查和依赖的锁定。希望这篇文章能给你带来新的启示。(作者:Azat Mardan ;翻译:可译网)

更多行业资讯,更新鲜的技术动态,尽在。


标签:Node

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn


为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP