10個技巧,讓你在2017年成為更好的Node開發者

2017-02-27 1412 0 編輯:深圳網站建設 來源:互聯網

1.避免復雜性 — 盡可能將你的代碼塊拆到最小,要小到極致。

2.使用異步編程 — 像躲避瘟疫般避免使用同步代碼。

3.避免require阻塞 — 把你所有的require聲明都放在文件的頂部,因為require是同步的,會阻塞代碼運行。

4.了解require緩存 — 了解它則可以利用它,否則它可能會帶來bug。

5.始終檢查錯誤 — 錯誤不是足球,任何時候都不要拋出錯誤或者跳過錯誤檢查。

6.只在同步代碼中使用try…catch — 在異步代碼中try...catch是沒有作用的。V8引擎針對try...catch無法進行優化。

7.返回callbacks或者使用if … else — 返回一個callback只是為了確保不繼續執行。

8.監聽錯誤事件 — 幾乎所有的Node的類/對象都有event emitter(觀察者模式)并且會廣播error事件,確保你監聽了它們。

9.了解你的npm — 使用-S或者-D來安裝模塊來代替--save或者--save-dev`。

10.在package.json中使用精確的版本號: npm在使用-S來安裝模塊時會自動使用默認的版本號,你需要手動修改去鎖定版本號。除非是開源模塊,否者不要相信你的項目中的SemVer(語義化版本標準)。

11.加分 — 使用不同的依賴。把項目在開發階段需要的東西放在 devDependencies 中,記得使用 npm i --production。多余的依賴越多,出現問題的風險就越大。

好的,接下來讓我們一個個單獨地去了解上面的每一點。

避免復雜性

讓我看一眼npm的創造者Isaac Z. Schlueter寫的一些模塊,例如,use-strict,這個模塊是用來在Javascript中強制使用嚴格模式,這個模塊僅僅只有三行代碼:

var module = require('module')

module.wrapper[0] += '"use strict";'

Object.freeze(module.wrap)

所以我們為什么要避免復雜性呢? 一個起源于美國海軍的著名短語:KEEP IT SIMPLE STUPID(或者是“Keep it simple, stupid”)。這就是原因。事實說明,人類大腦在任何一個時間只能在


其工作記憶中保持五到七個項目。

把你的代碼模塊化成一個更加小的部分,你和其他的開發者會更加好的理解它。你也可以更加好的去測試它。如下例子,

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的異步代碼中


當然也會有left-pad 事件,但是其實它只是影響了依賴于left-pad模塊的項目而且11分鐘后就發布了替代品。代碼的最小化帶來的好處超過了它的缺點。npm已經改變了發布策略,任何重要的


項目都應該使用緩存或私有的源(作為臨時解決方案)。

使用異步編程

在Node中同步代碼只要很小的一部分。這些代碼大多數都是用于命令行工具或者其他與web應用無關的腳本。Node開發者大多數都是編寫web應用,因此使用異步代碼可以避免阻塞現場。

例如,當你在編寫一個數據庫的腳本或者是一個不需要控制并行的任務時,下面這種寫法可能是可以的:

let data = fs.readFileSync('./acconts.json')

db.collection('accounts').insert(data, (results))=>{

  fs.writeFileSync('./accountIDs.json', results, ()=>{process.exit(1)})

})

但是當你創建一個web應用時,下面這個寫法會更好:

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()})

    })

  })

})

這個區別在于你是否需要編寫一個并發(通常是長期運行)或者非并發(短期運行)的系統。根據經驗來說,總是要在Node中使用異步代碼。


避免require阻塞


Node有一個使用了CommonJS模塊格式的簡單的模塊加載系統。它是基于require函數,require函數可以很方便的在不同的文件中引入模塊。和AMD/requirejs不同,Node/CommonJS的模塊加載


時同步的。require的工作方式是:引入一個模塊或者一個文件export的內容:


`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)

})

專業的網站建設公司,深正互聯,如您有網站營銷需求,請您關注我們,或者致電13828884598

本站文章均為深正網站建設摘自權威資料,書籍,或網絡原創文章,如有版權糾紛或者違規問題,請即刻聯系我們刪除,我們歡迎您分享,引用和轉載,但謝絕直接搬磚和抄襲!感謝...
關注深正互聯
我們猜你喜歡
七星彩头尾