Nachfolgend liste ich 10 Vorschläge auf, die Ihnen helfen können, 2017 ein besserer Node-Entwickler zu werden. Einige dieser Ratschläge habe ich in meiner täglichen Praxis gelernt, andere habe ich von den Leuten gelernt, die die beliebtesten Node- und NPM-Module geschrieben haben. Folgendes werden wir behandeln:
1. Vermeiden Sie Komplexität – Teilen Sie Ihre Codeblöcke in die kleinstmögliche Größe auf, so klein wie möglich.
2. Verwenden Sie asynchrone Programmierung – Vermeiden Sie synchronen Code wie die Pest.
3.Require-Blockierung vermeiden – Platzieren Sie alle Ihre require-Anweisungen oben in der Datei, da require synchron ist und die Ausführung des Codes blockiert.
4.Verstehen Sie den erforderlichen Cache – Wenn Sie ihn kennen, können Sie ihn nutzen, sonst kann es zu Fehlern kommen.
5.Immer auf Fehler prüfen – Fehler sind kein Fußball, wirf niemals Fehler aus und überspringe zu keinem Zeitpunkt die Fehlerprüfung.
6.Verwenden Sie try...catch nur in synchronem Code – try...catch hat keine Auswirkung in asynchronem Code. Der V8-Motor kann nicht für try...catch optimiert werden.
7.Rückrufe zurückgeben oder verwenden, wenn ... sonst – Einen Rückruf zurückgeben, nur um sicherzustellen, dass die Ausführung nicht fortgesetzt wird.
8.Fehlerereignisse abhören – Fast alle Node-Klassen/-Objekte verfügen über Ereignisemitter (Beobachtermodus) und übertragen Fehlerereignisse. Stellen Sie sicher, dass Sie diese abhören.
9.Kennen Sie Ihr npm – Verwenden Sie -S oder -D, um Module zu installieren, anstelle von --save oder --save-dev`.
10.Verwenden Sie die genaue Versionsnummer in package.json: npm verwendet automatisch die Standardversionsnummer, wenn Sie -S zum Installieren des Moduls verwenden. Sie müssen sie manuell ändern, um das zu sperren Versionsnummer. Vertrauen Sie SemVer (Semantic Versioning Standard) in Ihrem Projekt nicht, es sei denn, es handelt sich um ein Open-Source-Modul.
11. Bonuspunkte – Verwendung verschiedener Abhängigkeiten. Legen Sie die Dinge, die das Projekt während der Entwicklungsphase benötigt, in devDependencies ab und denken Sie daran, npm i --produktion zu verwenden. Je mehr redundante Abhängigkeiten Sie haben, desto größer ist das Risiko von Problemen.
Okay, lassen Sie uns jeden der oben genannten Punkte einzeln verstehen.
Komplexität vermeiden
Lassen Sie mich einen Blick darauf werfen npm Einige von Isaac Z. Schlueter, dem Erfinder von, geschriebene Module, zum Beispiel use-strict, werden verwendet, um die Verwendung des strikten Modus in Javascript zu erzwingen. Dieses Modul enthält nur drei Codezeilen:
var module = require('module') module.wrapper[0] += '"use strict";' Object.freeze(module.wrap)
Warum sollten wir Komplexität vermeiden? Ein berühmter Satz stammt von der US-Marine: KEEP IT SIMPLE STUPID (oder „Keep it simple, dumm“). Deshalb. Es stellt sich heraus, dass das menschliche Gehirn jeweils nur fünf bis sieben Elemente gleichzeitig in seinem Arbeitsgedächtnis speichern kann.
Modulieren Sie Ihren Code in kleinere Teile, und Sie und andere Entwickler werden ihn besser verstehen. Sie können es auch besser testen. Als Beispiel:
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() })
oder
const auth = require('./middleware/auth.js') const db = require('./middleware/db.js')(db) app.use(auth, db)
Ich glaube, die meisten Leute werden das zweite Beispiel mögen, vor allem, weil man seine Funktion schon anhand des Namens verstehen kann. Damals, als Sie Code schrieben, dachten Sie wahrscheinlich, Sie wüssten, wie es funktioniert. Oder auch, wenn Sie zeigen möchten, wie clever Sie sind, indem Sie mehrere Funktionen auf derselben Leitung miteinander verbinden. Sie schreiben jedoch einen dummen Code. Wenn Sie denken, dass das Schreiben dieses Codes sehr kompliziert ist, wird es schwierig sein, ihn zu verstehen, wenn Sie sich diesen Code in Zukunft ansehen. Halten Sie Ihren Code einfach, insbesondere im asynchronen Code von Node.
Natürlich wird es ein Left-Pad-Ereignis geben, aber tatsächlich betrifft es nur Projekte, die vom Left-Pad-Modul abhängen, und 11 Minuten später wurde ein Ersatz veröffentlicht. Die Vorteile der Codeminimierung überwiegen ihre Nachteile. npm hat seine Veröffentlichungsrichtlinie geändert und alle ernsthaften Projekte sollten zwischengespeicherte oder private Repositorys verwenden (als vorübergehende Lösung).
Asynchrone Programmierung verwenden
Code in Node Just synchronisieren ein kleiner Teil. Der größte Teil dieses Codes ist für Befehlszeilentools oder andere Skripte bestimmt, die nichts mit Webanwendungen zu tun haben. Die meisten Node-Entwickler schreiben Webanwendungen, sodass durch die Verwendung von asynchronem Code eine Blockierung der Szene vermieden werden kann.
Wenn Sie beispielsweise ein Datenbankskript oder eine Aufgabe schreiben, die keine Parallelitätskontrolle erfordert, kann die folgende Schreibweise in Ordnung sein:
let data = fs.readFileSync('./acconts.json') db.collection('accounts').insert(data, (results))=>{ fs.writeFileSync('./accountIDs.json', results, ()=>{process.exit(1)}) })
Aber wenn Sie ein For-Web erstellen Für Anwendungen wäre die folgende Schreibweise besser:
app.use('/seed/:name', (req, res) => { let data = fs.readFile(`./${req.params.name}.json`, ()=>{ db.collection(req.params.name).insert(data, (results))=>{ fs.writeFile(`./${req.params.name}IDs.json`, results, ()={res.status(201).send()}) }) }) })
Der Unterschied liegt darin, ob Sie ein gleichzeitiges (normalerweise langlaufendes) oder nicht gleichzeitiges (kurzfristiges) System schreiben müssen. Als Faustregel gilt: Verwenden Sie in Node immer asynchronen Code.
Anforderungsblockierung vermeiden
Knoten hat eine Verwendung A einfaches Modulladesystem für das CommonJS-Modulformat. Es basiert auf der Funktion require, mit der Module problemlos in verschiedene Dateien eingeführt werden können. Im Gegensatz zu AMD/requirejs werden Node/CommonJS-Module synchron geladen. Die Art und Weise, wie require funktioniert, besteht darin, den Inhalt eines Moduls oder eines Dateiexports einzuführen:
`const react = require('react')`
但是大多数的开发者并不知道require是会被缓存的。因此,只要解析的文件名(resolved filename)没有剧烈的变化(比如npm模块不存在的情况),模块的代码只会被执行并存入变量中一次(在当前进程中)。这是一个很好的优化。当然,即使有了缓存,你最好还是把你的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在同步代码中是可以被用的。前面的代码片段可以被更好的重构为:
request.get('/accounts', (error, response)=>{ try { data = JSON.parse(response) } catch(error) { // Will be called console.error(error) } })
如果我们无法将request的返回内容包裹在try...catch中,那么我们将没有办法去处理请求的错误。Node的开发者通过在返回的参数里面加上error来解决了这个问题。因此,我们需要在每一个回调中手动去处理错误。你可以去检查这些错误(判断error不是null),然后展示错误信息给用户或者展示在客户端上并且记录它, 或者你可以通过调用 callback ,给它传 error 参数,将错误传回给上一级调用栈(如果你在调用栈之上有另一个回调函数)。
request.get('/accounts', (error, response)=>{ if (error) return console.error(error) try { data = JSON.parse(response) } catch(error) { console.error(error) } })
一个小技巧是你可以使用okay库。你可以像下面的例子一样使用它去避免在回调地狱中手动去检查错误(你好, 回调地狱).
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!')
请确保使用return去阻止代码的继续执行。
监听 error 事件
Node中几乎所有的类/对象都有事件分发器(观察者模式)并且会广播 error 事件。 这是一个很好的特性,可以使开发者在这些讨厌的错误造成巨大后果之前捕捉到它们。
养成一个通过.on()来创建error事件监听的好习惯:
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会在安装模块的同时,会在package.json保存一条含有模块版本信息的条目。当然,还有--save-dev可以用于安装devDependencies(在生成环境中不需要的模块)。但是你知道用-S和-D是否可以代替--save 和--save-dev么?答案是可以的。
当你安装模块的时候,你需要删除-S和-D自动为你模块的版本号添加的^标签。否者当你使用npm install(或者npm i)安装模块的时候,就会自动拉取最新的镜像(版本号的第二位数字)。例如v6.1.0就是v6.2.0的一个镜像分支。
npm团队推荐使用semver,但是你最好不要这样。npm团队认为开源开发者会遵守semver所以他们在npm安装时自动加上了^。没有人可以去保证,所以最好是锁定你的版本号。更好的办法是使用shrinkwrap:npm shrinkwrap会生成一个包含依赖的具体版本的文件。