Ci-dessous, je vais énumérer 10 suggestions qui peuvent vous aider à devenir un meilleur développeur Node en 2017. Certains de ces conseils sont quelque chose que j'ai appris dans ma pratique quotidienne, et d'autres sont quelque chose que j'ai appris des personnes qui ont écrit les modules Node et npm les plus populaires. Voici ce que nous allons aborder :
1. Évitez la complexité — Divisez vos blocs de code dans la plus petite taille possible, aussi petite que possible.
2. Utilisez la programmation asynchrone — Évitez le code synchrone comme la peste.
3.Évitez le blocage de require — Placez toutes vos instructions require en haut du fichier, car require est synchrone et bloquera l'exécution du code.
4.Comprenez le cache requis — Si vous le connaissez, vous pouvez en profiter, sinon cela pourrait provoquer des bugs.
5.Toujours vérifier les erreurs — Les erreurs ne sont pas du football, ne lancez jamais d'erreurs et ne sautez jamais la vérification des erreurs.
6.Utilisez uniquement try...catch dans le code synchrone — try...catch n'a aucun effet dans le code asynchrone. Le moteur V8 ne peut pas être optimisé pour try...catch.
7.Renvoyer les rappels ou utiliser if ... else — Renvoie un rappel juste pour garantir que l'exécution ne continue pas.
8.Écouter les événements d'erreur — Presque toutes les classes/objets Node ont des émetteurs d'événements (mode observateur) et diffuseront les événements d'erreur, assurez-vous de les écouter.
9.Connaissez votre npm — Utilisez -S ou -D pour installer des modules au lieu de --save ou --save-dev`.
10.Utilisez le numéro de version exact dans package.json : npm utilisera automatiquement le numéro de version par défaut lors de l'utilisation de -S pour installer le module. Vous devez le modifier manuellement pour verrouiller le module. numéro de version. À moins qu'il ne s'agisse d'un module open source, ne faites pas confiance à SemVer (Semantic Versioning Standard) dans votre projet.
11. Points bonus — en utilisant différentes dépendances. Mettez les éléments dont le projet a besoin pendant la phase de développement dans devDependencies, n'oubliez pas d'utiliser npm i --production. Plus vous avez de dépendances redondantes, plus le risque de problèmes est grand.
D’accord, comprenons chacun des points ci-dessus un par un.
Éviter la complexité
Laissez-moi jeter un œil à npm Certains modules écrits par Isaac Z. Schlueter, le créateur de , par exemple use-strict, ce module est utilisé pour forcer l'utilisation du mode strict en Javascript. Ce module ne comporte que trois lignes de code :
var module = require('module') module.wrapper[0] += '"use strict";' Object.freeze(module.wrap)
Alors pourquoi éviter la complexité ? Une phrase célèbre originaire de l'US Navy : KEEP IT SIMPLE STUPID (ou "Keep it simple, stupid"). C'est pourquoi. Il s’avère que le cerveau humain ne peut conserver que cinq à sept éléments à la fois dans sa mémoire de travail.
Modulez votre code en morceaux plus petits, et vous et les autres développeurs le comprendrez mieux. Vous pouvez également mieux le tester. Par exemple,
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() })
ou
const auth = require('./middleware/auth.js') const db = require('./middleware/db.js')(db) app.use(auth, db)
Je pense que la plupart des gens aimeront le deuxième exemple, d'autant plus que vous pouvez comprendre sa fonction simplement en regardant le nom. À l’époque, lorsque vous écriviez du code, vous pensiez probablement savoir comment cela fonctionnait. Ou même si vous souhaitez montrer à quel point vous êtes intelligent en connectant plusieurs fonctions entre elles sur la même ligne. Cependant, vous écrivez un morceau de code stupide. Si vous pensez très compliqué à écrire ce code, il sera difficile de le comprendre lorsque vous regarderez ce code à l'avenir. Gardez votre code simple, en particulier dans le code asynchrone de Node.
Bien sûr, il y aura un événement du pavé gauche, mais en fait, cela n'affecte que les projets qui dépendent du module du pavé gauche et un remplacement a été publié 11 minutes plus tard. Les avantages de la minimisation du code dépassent ses inconvénients. npm a modifié sa politique de publication et tout projet sérieux doit utiliser des référentiels mis en cache ou privés (comme solution temporaire).
Utiliser la programmation asynchrone
Synchroniser le code dans Node Just une petite partie. La plupart de ce code est destiné aux outils de ligne de commande ou à d'autres scripts qui n'ont rien à voir avec les applications Web. La plupart des développeurs Node écrivent des applications Web, donc l'utilisation de code asynchrone peut éviter de bloquer la scène.
Par exemple, lorsque vous écrivez un script de base de données ou une tâche qui n'a pas besoin de contrôler le parallélisme, l'écriture suivante peut être OK :
let data = fs.readFileSync('./acconts.json') db.collection('accounts').insert(data, (results))=>{ fs.writeFileSync('./accountIDs.json', results, ()=>{process.exit(1)}) })
Mais lorsque vous créez un Pour le web applications, l'écriture suivante serait meilleure :
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()}) }) }) })
La différence réside dans le fait que vous devez écrire un système concurrent (généralement de longue durée) ou non simultané (de courte durée). En règle générale, utilisez toujours du code asynchrone dans Node.
Éviter d'exiger le blocage
Le nœud a une utilité A système de chargement de module simple pour le format de module CommonJS. Il est basé sur la fonction require, qui permet d'introduire facilement des modules dans différents fichiers. Contrairement à AMD/requirejs, les modules Node/CommonJS sont chargés de manière synchrone. La façon dont require fonctionne est d'introduire le contenu d'un module ou d'un export de fichier :
`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会生成一个包含依赖的具体版本的文件。