如何正確學習Node

0 :Node.js簡介

如今,愈來愈多的科技公司和開發者開始使用 Node.js 開發各類應用。Node.js除了可以輔助大前端開發外,還能夠編寫Web應用,封裝Api,組裝RPC服務等,甚至是開發VSCode編輯器同樣的PC客戶端。和其它技術相比, Node.js 簡單易學,性能好、部署容易,可以輕鬆處理高併發場景下的大量服務器請求。Node.js 周邊的生態也很是強大,NPM(Node包管理)上有超過60萬個模塊,日下超過載量3億次。但編寫 Node.js 代碼對新人和其它語言背景的開發者來講,不是一件容易的事,在入門以前須要弄懂很多複雜的概念。前端

a)Node.js簡介vue

  • 優勢: Node.js 不是一門語言也不是框架,它只是基於 Google V8 引擎的 JavaScript 運行時環境,同時結合 Libuv 擴展了 JavaScript 功能,使之支持 io、fs 等只有語言纔有的特性,使得 JavaScript 可以同時具備 DOM 操做(瀏覽器)和 I/O、文件讀寫、操做數據庫(服務器端)等能力,是目前最簡單的全棧式語言。

早在2007年,Jeff Atwood 就提出了著名的 Atwood定律java

任何可以用 JavaScript 實現的應用系統,最終都必將用 JavaScript 實現node

  • 缺點:

固然了,Node.js 也有一些缺點。Node.js 常常被人們吐槽的一點就是:回調太多難於控制(俗稱回調地獄)和 CPU 密集任務處理的不是很好。可是,目前異步流程技術已經取得了很是不錯的進步,從Callback、Promise 到 Async函數,能夠輕鬆的知足全部開發需求。至於 CPU 密集任務處理並不是不可解,方案有不少,好比經過系統底層語言 Rust 來擴展 Node.js,但這樣會比較麻煩。筆者堅信在合適的場景使用合適的東西,尤爲是在微服務架構下,一切都是服務,能夠作到語言無關。若是你們想使 JavaScript 作 CPU 密集任務,推薦 Node.js 的兄弟項目 fibjs,基於纖程(fiber,能夠簡單理解爲更輕量級的線程),效率很是高,兼容npm,同時沒有異步回調煩惱。 b)什麼是Node.js?mysql

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.react

  • Node.js 不是 JavaScript 應用,不是語言(JavaScript 是語言),不是像 Rails(Ruby)、 Laravel(PHP) 或 Django(Python) 同樣的框架,也不是像 Nginx 同樣的 Web 服務器。Node.js 是 JavaScript 運行時環境
  • 構建在 Chrome's V8 這個著名的 JavaScript 引擎之上,Chrome V8 引擎以 C/C++ 爲主,至關於使用JavaScript 寫法,轉成 C/C++ 調用,大大的下降了學習成本
  • 事件驅動(event-driven),非阻塞 I/O 模型(non-blocking I/O model),簡單點講就是每一個函數都是異步的,最後由 Libuv 這個 C/C++ 編寫的事件循環處理庫來處理這些 I/O 操做,隱藏了非阻塞 I/O 的具體細節,簡化併發編程模型,讓你能夠輕鬆的編寫高性能的Web應用,因此它是輕量(lightweight)且高效(efficient)的
  • 使用 npm 做爲包管理器,目前 npm 是開源庫裏包管理最大的生態,功能強大,截止到2017年12月,模塊數量超過 60 萬+
  • 應用: 大多數人都認爲 Node.js 只能寫網站後臺或者前端工具,這實際上是不全面的,Node.js的目標是讓併發編程更簡單,主要應用在以網絡編程爲主的 I/O 密集型應用。它是開源的,跨平臺,而且高效(尤爲是I/O處理),包括IBM、Microsoft、Yahoo、SAP、PayPal、沃爾瑪及GoDaddy都是 Node.js 的用戶。

c)基本原理jquery

下面是一張 Node.js 早期的架構圖,來自 Node.js 之父 Ryan Dahl 的演講稿,在今天依然不過期,它簡要的介紹了 Node.js 是基於 Chrome V8引擎構建的,由事件循環(Event Loop)分發 I/O 任務,最終工做線程(Work Thread)將任務丟到線程池(Thread Pool)裏去執行,而事件循環只要等待執行結果就能夠了。 git

核心概念程序員

  • Chrome V8 是 Google 發佈的開源 JavaScript 引擎,採用 C/C++ 編寫,在 Google 的 Chrome 瀏覽器中被使用。Chrome V8 引擎能夠獨立運行,也能夠用來嵌入到 C/C++ 應用程序中執行。
  • Event Loop 事件循環(由 libuv 提供)
  • Thread Pool 線程池(由 libuv 提供)

梳理一下es6

  • Chrome V8 是 JavaScript 引擎
  • Node.js 內置 Chrome V8 引擎,因此它使用的 JavaScript 語法
  • JavaScript 語言的一大特色就是單線程,也就是說,同一個時間只能作一件事
  • 單線程就意味着,全部任務須要排隊,前一個任務結束,纔會執行後一個任務。若是前一個任務耗時很長,後一個任務就不得不一直等着。
  • 若是排隊是由於計算量大,CPU 忙不過來,倒也算了,可是不少時候 CPU 是閒着的,由於 I/O 很慢,不得不等着結果出來,再往下執行
  • CPU 徹底能夠無論 I/O 設備,掛起處於等待中的任務,先運行排在後面的任務
  • 將等待中的 I/O 任務放到 Event Loop 裏
  • 由 Event Loop 將 I/O 任務放到線程池裏
  • 只要有資源,就盡力執行
  • Chrome V8 解釋並執行 JavaScript 代碼(這就是爲何瀏覽器能執行 JavaScript 緣由)
  • libuv 由事件循環和線程池組成,負責全部 I/O 任務的分發與執行

1. 前言:學習 Node.js 的三個境界

  • 打日誌:console.log
  • 斷點調試:斷點調試:node debugger 或node inspector 或vscode
  • 測試驅動開發(tdd | bdd)

2. 準備與學習:

基礎學習

1)js語法必須會

  1. js基本語法,都是c語系的,有其餘語言背景學習起來相對更簡單
  2. 常見用法,好比正則,好比數據結構,尤爲是數組的幾種用法。好比bind/call/apply等等
  3. 面向對象寫法。js是基於對象的,因此它的oo寫起來很是詭異。參見紅皮書JavaScript高級編程,不少框架都是本身實現oo基礎框架,好比ext-core等。

2)我的學習和技術選型都要按部就班

  1. 先能寫,採用面向過程寫法,簡單理解就是定義一堆function,而後調用,很是簡單
  2. 而後再追求更好的寫法,能夠面向對象。對於規模化的編程來講,oo是有它的優點的,通常java、c#,ruby這些語言裏都有面向對象,因此後端更習慣,但對於語言經驗不那麼強的前端來講算高級技巧。
  3. 等oo玩膩了,能夠有更好的追求:函數式編程,不管編程思惟,仍是用法上都對已有的編程思惟是個挑戰。我很喜歡函數式,但不太會在團隊裏使用,畢竟oo階段還沒徹底掌握,風險會比較大。但若是團隊水平都很是高了,團隊穩定是能夠用的。

能夠看出個人思路,先能寫,而後再追求更好的寫法,好比面向對象。等團隊水平到必定程度了,而且穩定的時候,能夠考慮更加極致的函數式寫法。

3)各類高級的JavaScript友好語言

JavaScript友好語言指的是可以使用其餘語法實現,但最終編譯成js的語言。自從Node.js出現後,這種黑科技層出不窮。好比比較有名的coffee、typescript、babel(es)等。

CoffeeScript雖然也是JavaScript友好語言,但其語法借鑑ruby,崇尚極簡,對於類型和OO機制上仍是偏弱,並且這麼多年也沒發展起來,仍然是比較小衆的活着。將來比例會愈來愈少的。

顯然TypeScript會愈來愈好,TypeScript 的強大之處是要用過才知道的。

  • 1)規模化編程,像Java那種,靜態類型,面向對象,前端只有TypeScript能作到
  • 2)親爹是微軟安德斯·海爾斯伯格,不知道此人的請看borland傳奇去
  • 3)開源,將來很好
  • 4)組合拳:TypeScript + VSCode = 神器

當下前端發展速度極快,以指數級的曲線增加。之前可能1年都不必定有一項新技術,如今可能每月都有。大前端,Node全棧,架構演進等等都在快速變化。能夠說,前端越複雜,有越多的不肯定性,TypeScript的機會就越大。 4)再論面向對象

面向對象想用好也不容易的,並且js裏有各類實現,真是讓人眼花繚亂。

  • 基於原型的寫法,縱觀JavaScript高級編程,就是翻來覆去的講這個,這個很基礎,但很差是很好用。能夠不用,但不能夠不會。
  • 本身寫面向對象機制是最好的,但不是每一個人都有這個能力的。好在es6規範出了更好一點的面向對象,經過class、extends、super關鍵字來定義類,已經明顯好不少了,雖然還很弱,但起碼勉強能用起來了。從面向過程走過來的同窗,推薦這種寫法,簡單易用。但要注意面向對象要有面向對象的寫法,要理解抽象,繼承,封裝,多態4個基本特徵。若是想用好,你甚至還須要看一些設計模式相關的書。好在有《JavaScript設計模式》一書。Koa2裏已經在用這種寫法了。
  • js是腳本語言,解釋便可執行。因此它的最大缺點是沒有類型系統,這在規模化編程裏是很是危險的,一個函數,傳參就能玩死人。因而如今流行使用flow和typescript來作類型校驗。flow只是工具,比較輕量級。而typescript是es6超級,給es6補充了類型系統和更完善的面向對象機制,因此大部分人都會對ts有好感,頗有多是將來的趨勢。

Node.js應用場景

《Node.js in action》一書裏說,Node.js 所針對的應用程序有一個專門的簡稱:DIRT。它表示數據密集型實時(data-intensive real-time)程序。由於 Node.js 自身在 I/O 上很是輕量,它善於將數據從一個管道混排或代理到另外一個管道上,這能在處理大量請求時持有不少開放的鏈接,而且只佔用一小部份內存。它的設計目標是保證響應能力,跟瀏覽器同樣。

這話不假,但在今天來看,DIRT 仍是範圍小了。其實 DIRT 本質上說的 I/O 處理的都算,但隨着大前端的發展,Node.js 已經再也不只是 I/O 處理相關,而是更加的「Node」!

  • 1)跨平臺:覆蓋你能想到的面向用戶的全部平臺,傳統的PC Web端,以及PC客戶端 nw.js/electron 、移動端 cordova、HTML五、react-nativeweex,硬件 ruff.io
  • 2)Web應用開發:網站、Api、RPC服務等
  • 3)前端:三大框架 React \ Vue \ Angular 輔助開發,以及工程化演進過程(使用Gulp /Webpack 構建 Web 開發工具)
  • 4)工具:npm上各類工具模塊,包括各類前端預編譯、構建工具 Grunt / Gulp、腳手架,命令行工具,各類奇技淫巧等

Node.js 應用場景很是豐富,好比 Node.js 能夠開發操做系統,但通常我都不講的,就算說了也沒多大意義,難道你們真的會用嗎?通常,我習慣將 Node.js 應用場景氛圍7個部分。

1)初衷,server端,不想成了前端開發的基礎設施 2)命令行輔助工具,甚至能夠是運維 3)移動端:cordova,pc端:nw.js和electron 4)組件化,構建,代理 5)架構,先後端分離、api proxy 6)性能優化、反爬蟲與爬蟲 7) 全棧最便捷之路

Node核心:異步流程控制

Node.js是爲異步而生的,它本身把複雜的事兒作了(高併發,低延時),交給用戶的只是有點難用的Callback寫法。也正是坦誠的將異步回調暴露出來,纔有更好的流程控制方面的演進。也正是這些演進,讓Node.js從DIRT(數據敏感實時應用)擴展到更多的應用場景,今天的Node.js已經不僅是能寫後端的JavaScript,已經涵蓋了全部涉及到開發的各個方面,而Node全棧更是熱門種的熱門。

直面問題纔能有更好的解決方式,Node.js的異步是整個學習Node.js過程當中重中之重。

    1. 異步流程控制學習重點
  • 2)Api寫法:Error-first Callback 和 EventEmitter
  • 3)中流砥柱:Promise
  • 4)終極解決方案:Async/Await
  1. 異步流程控制學習重點

我整理了一張圖,更直觀一些。從09年到如今,8年多的時間裏,整個Node.js社區作了大量嘗試,其中曲折足足夠寫一本書的了。你們先簡單瞭解一下。

  • 紅色表明Promise,是使用最多的,不管async仍是generator均可用
  • 藍色是Generator,過分貨
  • 綠色是Async函數,趨勢

結論:Promise是必須會的,那你爲何不順勢而爲呢?

推薦:使用Async函數 + Promise組合,以下圖所示。

結論

  1. Node.js SDK裏callback寫法必須會的。
  2. Node.js學習重點: Async函數與Promise
    1. 中流砥柱:Promise
    2. 終極解決方案:Async/Await

2)Api寫法:Error-first Callback 和 EventEmitter a)Error-first Callback 定義錯誤優先的回調寫法只須要注意2條規則便可:

  • 回調函數的第一個參數返回的error對象,若是error發生了,它會做爲第一個err參數返回,若是沒有,通常作法是返回null。
  • 回調函數的第二個參數返回的是任何成功響應的結果數據。若是結果正常,沒有error發生,err會被設置爲null,並在第二個參數就出返回成功結果數據。

下面讓咱們看一下調用函數示例,Node.js 文檔裏最常採用下面這樣的回調方式:

function(err, res) {
  // process the error and result
}
複製代碼

這裏的 callback 指的是帶有2個參數的函數:"err"和 "res"。語義上講,非空的「err」至關於程序異常;而空的「err」至關於能夠正常返回結果「res」,無任何異常。 b)EventEmitter

事件模塊是 Node.js 內置的對觀察者模式「發佈/訂閱」(publish/subscribe)的實現,經過EventEmitter屬性,提供了一個構造函數。該構造函數的實例具備 on 方法,能夠用來監聽指定事件,並觸發回調函數。任意對象均可以發佈指定事件,被 EventEmitter 實例的 on 方法監聽到。

在node 6以後,能夠直接使用require('events')

var EventEmitter = require('events')
var util = require('util')

var MyEmitter = function () {
 
}
util.inherits(MyEmitter, EventEmitter)

const myEmitter = new MyEmitter();

myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
    // Prints: a b {}
});

myEmitter.emit('event', 'a', 'b');
複製代碼

和jquery、vue裏的Event是很是相似的。並且前端本身也有EventEmitter。 c)如何更好的查Node.js文檔

API是應用程序接口Application Programming Interface的簡稱。從Node.js異步原理,咱們能夠知道,核心在於 Node.js SDK 中API調用,而後交由EventLoop(Libuv)去執行,因此咱們必定要熟悉Node.js的API操做。

Node.js的API都是異步的,同步的函數是奢求,要查API文檔,在高併發場景下慎用。

筆者推薦使用 DashZeal 查看離線文檔,常常查看離線文檔,對Api理解會深刻不少,比IDE輔助要好,能夠有效避免離開IDE就不會寫代碼的窘境。 3)中流砥柱:Promise 回調地獄

Node.js 由於採用了錯誤優先的回調風格寫法,致使sdk裏導出都是回調函數。若是組合調用的話,就會特別痛苦,常常會出現回調裏嵌套回調的問題,你們都很是厭煩這種寫法,稱之爲Callback Hell,即回調地獄。一個經典的例子來自著名的Promise模塊q文檔裏。

step1(function (value1) {
    step2(value1, function(value2) {
        step3(value2, function(value3) {
            step4(value3, function(value4) {
                // Do something with value4
            });
        });
    });
});
複製代碼

這裏只是作4步,嵌套了4層回調,若是更多步驟呢?不少新手淺嘗輒止,到這兒就望而卻步,粉轉黑。這明顯不夠成熟,最起碼你要看看它的應對解決方案吧! Node.js 約定全部Api都採用錯誤優先的回調方式,這部分場景都是你們直接調用接口,無太多變化。而Promise是對回調地獄的思考,或者說是改良方案。目前使用很是廣泛,能夠說是在async函數普及以前惟一一個通用性規範,甚至 Node.js 社區都在考慮 Promise 化,可見其影響之大。

Promise最先也是在commonjs社區提出來的,當時提出了不少規範。比較接受的是promise/A規範。後來人們在這個基礎上,提出了promise/A+規範,也就是實際上如今的業內推行的規範。ES6 也是採用的這種規範。 Promise意味着[許願|承諾]一個尚未完成的操做,但在將來會完成的。與Promise最主要的交互方法是經過將函數傳入它的then方法從而獲取得Promise最終的值或Promise最終最拒絕(reject)的緣由。要點有三個:

  • 遞歸,每一個異步操做返回的都是promise對象

  • 狀態機:三種狀態轉換,只在promise對象內部能夠控制,外部不能改變狀態

  • 全局異常處理 Async函數要點以下:

  • Async函數語義上很是好

  • Async不須要執行器,它自己具有執行能力,不像Generator須要co模塊

  • Async函數的異常處理採用try/catch和Promise的錯誤處理,很是強大

  • Await接Promise,Promise自身就足夠應對全部流程了,包括async函數沒有純並行處理機制,也能夠採用Promise裏的all和race來補齊

  • Await釋放Promise的組合能力,外加co和Promise的then,幾乎沒有不支持的場景

綜上所述

  • Async函數是趨勢,若是Chrome 52. v8 5.1已經支持Async函數(https://github.com/nodejs/CTC/issues/7)了,Node.js支持還會遠麼?
  • Async和Generator函數裏都支持promise,因此promise是必須會的。
  • Generator和yield異常強大,不過不會成爲主流,因此學會基本用法和promise就行了,不必全部的都必須會。
  • co做爲Generator執行器是不錯的,它更好的是當作Promise 包裝器,經過Generator支持yieldable,最後返回Promise,是否是有點無恥?
    1. 異步流程控制學習重點
  • 2)Api寫法:Error-first Callback 和 EventEmitter
  • 3)中流砥柱:Promise
  • 4)終極解決方案:Async/Await

Web編程要點

通常,後端開發指的是 Web 應用開發中和視圖渲染無關的部分,主要是和數據庫交互爲主的重業務型邏輯處理。但如今架構升級後,Node.js 承擔了先後端分離重任以後,有了更多玩法。從帶視圖的傳統Web應用面向Api接口應用,到經過 RPC 調用封裝對數據庫的操做,到提供前端 Api 代理和網關,服務組裝等,統稱爲後端開發,再也不是以往只有和數據庫打交道的部分纔算後端。這樣,就可讓前端工程師對開發過程可控,更好的進行調優和性能優化。 對 Node.js 來講,一直沒有在後端取得其合理的佔有率,緣由是多方面的,暫列幾條。

  • 1)利益分配,已有實現大可能是Java或者其餘語言,基本是無法撼動的,重寫的成本是巨大的,另外,若是用Node寫了,那麼那些寫Java的人怎麼辦?搶人飯碗,這是要拼命的。
  • 2)Node相對年輕,你們對Node的理解不夠,回調和異步流程控制略麻煩,不少架構師都不肯意花時間去學習。儘管在Web應用部分處理起來很是簡單高效,但在遇到問題時並不容易排查定位,對開發者水平要求略高。
  • 3)開發者技能單一,不少是從前端轉過來的,對數據庫,架構方面知識欠缺,對系統設計也知之很少,這是很危險的,有種麻桿打狼兩頭懼怕的感受。
  • 4)Node在科普、培訓、佈道等方面作的並很差,國外使用的很是多,國內卻不多人知道,不如某些語言作得好。

儘管如此,Node.js 仍是盡人皆知,捲入各類是非風口,也算是在大前端浪潮中大紅大紫。緣由它的定位很是明確,補足以 JavaScript 爲核心的全棧體系中服務器部分。開發也是人,可以同時掌握並精通多門語言的人畢竟很少,並且程序員的美德是「懶」,能使用 JavaScript 一門語言完成全部事兒,爲何要學更多呢? 咱們能夠根據框架的特性進行分類

框架名稱 特性 點評
Express 簡單、實用,路由中間件等五臟俱全 最著名的Web框架
Derby.js && Meteor 同構 先後端都放到一塊兒,模糊了開發便捷,看上去更簡單,實際上上對開發來講要求更高
Sails、Total 面向其餘語言,Ruby、PHP等 借鑑業界優秀實現,也是 Node.js 成熟的一個標誌
MEAN.js 面向架構 相似於腳手架,又指望同構,結果只是蹭了熱點
Hapi和Restfy 面向Api && 微服務 移動互聯網時代Api的做用被放大,故而獨立分類。尤爲是對於微服務開發更是利器
ThinkJS 面向新特性 借鑑ThinkPHP,並慢慢走出本身的一條路,對於Async函數等新特性支持,無出其右,新版v3.0是基於Koa v2.0的做爲內核的
Koa 專一於異步流程改進 下一代Web框架
Egg 基於Koa,在開發上有極大便利 企業級Web開發框架

對於框架選型

  • 業務場景、特色,沒必要爲了什麼而什麼,避免本末倒置
  • 自身團隊能力、喜愛,有時候技術選型決定團隊氛圍的,須要平衡激進與穩定
  • 出現問題的時候,有人可以作到源碼級定製。Node.js 已經有8年曆史,但模塊完善程度參差不齊,若是不慎踩到一個坑裏,須要團隊在無外力的狀況可以搞定,不然會影響進度

Tips:我的學習求新,企業架構求穩,無非喜愛與場景而已 Web編程核心

  • 異步流程控制(前面講過了)

  • 基本框架 Koa或Express,新手推薦Express,畢竟資料多,上手更容易。若是有必定經驗,推薦Koa,其實這些都是爲了瞭解Web編程原理,尤爲是中間件機制理解。

  • 數據庫 mongodb或mysql都行,mongoose和Sequelize、bookshelf,TypeOrm等都很是不錯。對於事物,不是Node.js的鍋,是你選的數據庫的問題。另一些偏門,想node連sqlserver等估計還不成熟,我是不會這樣用的。

  • 模板引擎, ejs,jade,nunjucks。理解原理最好。尤爲是extend,include等高級用法,理解佈局,複用的好處。其實先後端思路都是同樣的。

  • Node 的書幾乎都過期了,我該買哪本?

  • Node 用途那麼多,我該從哪裏學起?

  • Node Web 框架那麼多,我該怎麼選?

相關文章
相關標籤/搜索