Node.js不是一門語言也不是框架,他只是基於Google V8引擎的JavaScript運行時環境,同時結合Libuv擴展了JavaScript功能,使之支持io、fs等只有語言纔有的特性,使得JavaScript可以同時具備DOM操做(瀏覽器)和I/O、文件讀寫、操做數據庫(服務器端)等能力,是目前最簡單的全棧式語言。前端
Node.js一般被用來開發低延遲的網絡應用,也就是那些須要在服務器端環境和前端實時收集和交換數據的應用(API、即時聊天、微服務)。node
總結:Node.js是構建在JavaScript之上的,事件觸發和異步的,專爲數據密集型實時程序設計的。其目標是讓併發編程更簡單,,主要應用在以網絡編程爲主的 I/O 密集型應用。他是開源的,跨平臺,而且高效(尤爲是 I/O 處理)react
下面是一張 Node.js 早期的架構圖,來自 Node.js 之父 Ryan Dahl 的演講稿,在今天依然不過期,它簡要的介紹了 Node.js 是基於 Chrome V8引擎構建的,由事件循環(Event Loop)分發 I/O 任務,最終工做線程(Work Thread)將任務丟到線程池(Thread Pool)裏去執行,而事件循環只要等待執行結果就能夠了。git
核心概念github
梳理一下數據庫
核心express
libuv
由事件循環和線程池組成,負責全部 I/O 任務的分發與執行在解決併發問題上,異步是最好的解決方案,能夠拿排隊和叫號機來理解npm
Node.js簡稱 數據密集型實時程序(DIRT)。由於Node.js自身在I/O 上很是輕量,它善於將數據從一個管道混排或代理到另外一個官道上,這能在處理大量請求時持有不少開放的鏈接,而且只佔用一小部份內存。它的設計目標是保證影響能力,跟瀏覽器同樣。編程
Node.js使用場景主要分爲4大類:react-native
nw.js/electron
、移動端 cordova
、HTML五、react-native
、weex
,硬件 ruff.io
等Vue
\ Angular
輔助開發,以及工程化演進過程(使用Gulp
/Webpack 構建 Web 開發工具)npm
上各類工具模塊,包括各類前端預編譯、構建工具 Grunt
/ Gulp
、腳手架,命令行工具,各類奇技淫巧等Node.js是爲異步而生的,他把複雜的事情都給作了(高併發,低延時),交給用戶的只是有點難用的Callback寫法。
直面問題纔能有更好的解決方式,Node.js的異步是整個學習Node.js過程當中的重中之重。
a)Error-first Callback 定義錯誤優先的回調寫法只須要注意2條規則便可:
b)EventEmitter
事件模塊是 Node.js 內置的對觀察者模式「發佈/訂閱」(publish/subscribe)的實現,經過EventEmitter
屬性,提供了一個構造函數。該構造函數的實例具備 on
方法,能夠用來監聽指定事件,並觸發回調函數。任意對象均可以發佈指定事件,被 EventEmitter
實例的 on
方法監聽到。
Node.js的API都是異步的,同步的函數是奢求,要查API文檔,在高併發場景下慎用。
回調地獄
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 }); }); }); });
Promise意味着[許願|承諾]一個尚未完成的操做,但在將來會完成的。與Promise最主要的交互方法是經過將函數傳入它的then方法從而獲取得Promise最終的值或Promise最終最拒絕(reject)的緣由。要點有三個:
1)定義
var promise = new Promise(function(resolve, reject) { // do a thing, possibly async, then… if (/* everything turned out fine */) { resolve("Stuff worked!"); } else { reject(Error("It broke")); } });
每一個Promise定義都是同樣的,在構造函數裏傳入一個匿名函數,參數是 resolve 和 reject,分別表明成功和失敗時候的處理。
2)調用
promise.then(function(text){ console.log(text)// Stuff worked! return Promise.reject(new Error('我是故意的')) }).catch(function(err){ console.log(err) })
它的主要交互方式是經過then函數,若是Promise成功執行resolve了,那麼它就會將resolve的值傳給最近的then函數,做爲它的then函數的參數。若是出錯reject,那就交給catch來捕獲異常就行了。
Promise 的最大優點是標準化,各種異步工具庫都按照統一規範實現,即便是async幻術也能夠無縫集成。因此用 Promise 封裝API通用性強,用起來簡單,學習成本低。在async幻術普及以前,絕大部分應用都是採用 Promise來作異步流程控制的,因此掌握 Promise是Node.js學習必需要會的。
Async/Await是異步操做的終極解決方案,Koa 2在node 7.6發佈以後,立馬發佈了正式版本,而且推薦使用async函數來編寫Koa中間件。
這裏給出一段Koa 2應用裏的一段代碼
exports.list = async (ctx, next) => { try { let students = await Student.getAllAsync(); await ctx.render('students/index', { students : students }) } catch (err) { return ctx.api_error(err); } };
它作了3件事兒
4.1 正常寫法
const pkgConf = require('pkg-conf'); async function main(){ const config = await pkgConf('unicorn'); console.log(config.rainbow); //=> true } main();
變態寫法
const pkgConf = require('pkg-conf'); (async () => { const config = await pkgConf('unicorn'); console.log(config.rainbow); //=> true })();
4.2 await + Promise
const Promise = require('bluebird'); const fs = Promise.promisifyAll(require("fs")); async function main(){ const contents = await fs.readFileAsync("myfile.js", "utf8") console.log(contents); } main();
4.3 await + co + generator
const co = require('co'); const Promise = require('bluebird'); const fs = Promise.promisifyAll(require("fs")); async function main(){ const contents = co(function* () { var result = yield fs.readFileAsync("myfile.js", "utf8") return result; }) console.log(contents); } main();
由上面3中基本用法能夠推出Async函數要點以下:
小結
這部分共講了4個小點,都是極其直接的必須掌握的知識點。
這裏有一個練手的項目,感興趣的同窗能夠自行Download,相信會有所收穫:https://github.com/oceanMin/cms