Node.js技術總結

Node.js是什麼

官網定義:前端

Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境。 Node.js 使用了一個事件驅動、非阻塞式I/O 的模型,使其輕量又高效。

非阻塞 I/O 模型(non-blocking I/O model),簡單點講就是每一個函數都是異步的,最後由 Libuv 這個 C/C++ 編寫的事件循環處理庫來處理這些 I/O 操做,隱藏了非阻塞 I/O 的具體細節,簡化併發編程模型,讓你能夠輕鬆的編寫高性能的Web應用,因此它是輕量(lightweight)且高效(efficient)的。node

Node.js能作什麼

clipboard.png

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

Node核心:異步流程控制

clipboard.png

其實,通常使用是不須要掌握上圖中的全部技術的。對於初學者來講,先夠用,再去深究細節。因此,精簡一下,只瞭解3個就足夠足夠用了。
clipboard.pngreact

Promise 的最大優點是標準化,各種異步工具庫都按照統一規範實現,即便是async函數也能夠無縫集成。因此用 Promise 封裝 API 通用性強,用起來簡單,學習成本低。在async函數普及以前,絕大部分應用都是採用Promise來作異步流程控制的,因此掌握Promise是Node.js學習過程當中必需要掌握的重中之重。jquery

推薦學習資料
Node.js最新技術棧之Promise篇 https://cnodejs.org/topic/560...
理解 Promise 的工做原理 https://cnodejs.org/topic/569...
Promise 迷你書 http://liubin.github.io/promi...nginx

異步和事件觸發:瀏覽器

瀏覽器中非阻塞I/O的例子
clipboard.pnggit

異步和事件觸發:服務器

Node中的非阻塞I/O示例
clipboard.pnggithub

Node基於libuv實現跨平臺的架構示意圖

clipboard.png

Commonjs, AMD, CMD規範

CommonJSredis

  • 經過 require 來加載模塊。
  • 經過 exports 和 modul.exports 來暴露模塊中的內容。
// moduleA.js
module.exports = function( value ){
return value * 2;

// moduleB.js
var multiplyBy2 = require('./moduleA');
var result = multiplyBy2(4);

CommonJS是同步加載模塊,服務器端的Node.js遵循CommonJS規範。sql

require("module");
require("../file.js");
exports.doStuff = function() {};
module.exports = someValue;

AMD
AMD是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義"。AMD規範其實只有一個主要接口 define(id,dependencies,factory),它要在聲明模塊的時候指定全部的依賴dependencies,而且還要當作形參傳到factory中,對於依賴的模塊提早執行,依賴前置。

define("module", ["dep1", "dep2"], function(d1, d2) {
  return someExportedValue;
});
require(["module", "../file"], function(module, file) { /* ... */ });

CMD
CMD規範和AMD類似,儘可能保持簡單,而且與CommonJS和NodeJS的Modules規範保持了很大的兼容性。依賴就近,延遲執行。

define(function(require, exports, module) {
  var $ = require('jquery');
  var Spinning = require('./spinning');
  exports.doSomething = ...
  module.exports = ...
})

Node查找模塊的步驟

clipboard.png

中間件

中間件組件是一個JavaScript函數,按慣例會接受三個參數:一個請求對象, 一個響應對象,還有一個一般命名爲next的參數,它是一個回調函數,代表這個組件已經完成了它的工做,能夠執行下一個中間件組件了。

Connect
最小的Connect程序

var connect = require('connect');
var app = connect();
app.listen(3000);

日誌中間件

var connect = require('connect');

function logger(req, res, next) {
  console.log('%s %s', req.method, req.url);
  next();
}

function hello(req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.end('hello world');
}

connect()
  .use(logger)
  .use(hello)
  .listen(3000);

中間件的順序很重要

用中間件的順序執行認證

var connect = require('connect');
connect()
  .use(logger)
  .use(restrictFileAccess)
  .use(serveStaticFiles)
  .use(hello)
  .listen(3000);

掛載中間件和服務器

路由admin請求

function admin(req, res, next) {
  switch (req.url) {
    case '/':
      res.end('try /users');
      break;
    case '/users':
      res.setHeader('Content-Type', 'application/json');
      res.end(JSON.stringify(['tobi', 'loki', 'jane']));
      break;
  }  
}

掛載中間件或服務器

var connect = require('connect');
connect()
  .use(logger)
  .use('/admin', restrict)
  .use('/admin', admin)
  .use(hello)
  .listen(3000);

建立可配置中間件

function setup(options) {
  //  設置邏輯
  
  return function(req, res, next) {
    // 中間件邏輯
  }
}

app.use(setup({some: 'options'}));

建立可配置的logger中間件組件

var app = connect()
  .use(logger(':method :url'))
  .use(hello);

構建路由中間件組件

var connect = require('connect');
var router = require('./middleware/router');
var routes = {
  GET: {
    '/users': function(req, res) {
      res.end('tobi, loki, ferret');
    },
    '/user/:id': function(req, res, id) {
      res.end('user ' + id);  
    }
  },
  DELETE: {
    '/user/:id': function(req, res, id) {
       res.end('deleted user ' + id);
     }
  }
};

connect()
  .use(router(routes))
  .listen(3000);

由於程序裏中間件的數量沒有限制,中間件組件使用的次數也沒有限制,因此在一個程序中 有可能會定義幾個路由器。

var connect = require('connect');
var router = require('./middleware/router');

connect()
  .use(router(require('./routes/user')))
  .use(router(require('./routes/admin')))
  .listen(3000);

使用錯誤處理中間件

var connect = require('connect')

connect()
  .use(function hello(req, res) {
    foo();
    res.setHeader('Content-Type', 'text/plain');
    res.end('hello world');
  })
  .listen(3000);

默認狀況下,Connect給出的響應是狀態碼500,包含文本「Internal Server Error」以及錯誤自 身詳細信息的響應主體。

function errorHandler() {
  var env = process.env.NODE_ENV || 'development';
  return function(err, req, res, next) {
    res.statusCode = 500;
    switch (env) {
      case 'development':
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify(err));
        break;
      default:
        res.end('Server error);
    }
  }
}

Connect自帶的中間件

  • cookieParser(): 解析HTTP cookie
  • bodyParser(): 解析請求主體
  • limit(): 請求主體的限制
  • query(): 查詢字符串解析
  • logger(): 記錄請求
  • session(): 會話管理
  • static(): 靜態文件服務

數據存儲
內存, redis, mysql, mongodb, mongoose

express

渲染視圖
處理表單和文件上傳

koa

egg

部署

阿里雲,騰訊雲,域名,pm2,nginx,集羣,分佈式,docker,微服務

相關文章
相關標籤/搜索