1. 程式人生 > >nodejs知識結構

nodejs知識結構

javascrip 程序 exit and timeout log user isa tle

一、回調函數

node 的所有API都支持回調函數。阻塞是按順序執行的,而非阻塞是不需要按順序的,所以如果需要處理回調函數的參數,就需要些在函數內。

  • node 是單進程單線程應用程序,單因為 V8 引擎提供的異步執行回調接口,可以處理大量的並發,性能很高。
  • 幾乎所有的事件機制都是觀察者模式實現;
  • 每一個異步事件都生成一個事件觀察者,如果有事件發生就調用該回調函數;
  • 執行異步操作的函數將回調函數作為最後一個參數,回調函數接收錯誤對象作為第一個參數

二、事件驅動

  • web server 可以一直接受請求而不等待任何讀寫操作:稱之為非阻塞IO或者事件驅動IO;
  • 在事件驅動模型中,會生成一個主循環來監聽事件,當檢測到事件時觸發回調函數;
  • nodejs 所有異步io操作在完成時都會發送一個事件到事件隊列
  • 只要是支持事件響應的核心模塊都是 EventEmiiter 的子類
var events = require("events");
var eventEmitter = new events.EventEmitter();

// 定義事件觀察者、監聽器、或者叫處理器
var eventHandler = function handler(){
    console.log("handle event")
}

// 事件註冊
var eventEmitter.on("demo", eventHandler);

// 事件發布
var eventEmitter.emit("demo")

 三、buffer

buffer類用來創建一個專門存放二進制數據的緩沖區,buffer類似於一個整數數組。

3.1、支持的字符編碼

  • ascii
  • utf8
  • uft16le
  • ucs2
  • base64
  • latin1
  • binary
  • hex : 一個字節(8 bit)編碼為兩個十六進制字符

3.2、創建Buffer類

  • Buffer.alloc
  • Buffer.allocUnsafe
  • Buffer.allocUnfaseSlow
  • Buffer.from

3.3、寫緩沖區

  • buf.write

3.4、讀緩沖區

  • buf.toString
  • buf.toJSON()

四、Stream

  • http 服務器發起請求的 request 對象就是一個 Stream,stdout 也是一個Stream
  • Stream 對象都是 EventEmitter 實例,常用事件:data,end,error,finish
  • 四種類型: Readable,Writable,Duplex,Transform
  • 管道流:從一個流中獲取數據並將數據傳遞到另外一個流中;
  • 鏈式流:

五、模塊系統

  • 模塊是為了更好的代碼服用,文件和模塊一一對應,可以是 js 代碼,json,或者 c/c++ 擴展;

  • 模塊創建的兩種方式: exports, module.exports

exports.world = function () {
    console.log("hello world!")
}

  

function Hello() { 
    var name; 
    this.setName = function(thyName) { 
        name = thyName; 
    }; 
    this.sayHello = function() { 
        console.log(‘Hello ‘ + name); 
    }; 
}; 
module.exports = Hello;

  使用模塊:require

var hello = require(‘hello‘);
hello.world()

  

var Hello = require(‘./hello‘); 
hello = new Hello(); 
hello.setName(‘BYVoid‘); 
hello.sayHello(); 

  

  • 模塊類型:原生模塊(http, fs, path, os…), 相對路徑文件模塊,絕對路徑文件模塊,文件模塊
  • 模塊加載順序: 原生模塊 > 文件模塊, 優先從緩存中加載,緩存中沒有則從文件加載,並保存到緩存中。

六、函數

  • js 中的函數是第一類對象,可以作為參數或返回值
  • 匿名函數與lambda表達式:以更簡潔的形式進行函數對象的傳遞
function hello(say) {
    say();
}

hello(function(){
    console.log("hello node!");
})

hello(()=> console.log("hello lambda!"))

 七、路由

  • 輸入信息: url, get/post query parameters, request body
  • 在 web server 接收到新的 request 時,會解析輸入信息,並分發給特定的處理器,這裏的分發工作就是“路由”

a simple http server

var http = require("http");
var url = require("url");


function route(request){
    return url.parse(request.url).pathname;
}

http.createServer((request, response) => {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write(route(request));
    response.end();
}).listen(8888);

  

  • url.parse
{
    protocol: null,
    slashes: null,
    auth:null,
    host: null,
    port: null,
    hostname: null,
    hash: null,
    search: "?name=xxxxx&url=aaaaa",
    query: {
        name: ‘xxxxx‘,
        url: ‘aaaaa‘
    },
    pathname: ‘/user‘,
    path: ‘/username=xxxxx&url=aaaaa?‘,
    href: ‘name=xxxxx&url=aaaaa‘
}

  

  • 接收請求體:請求體傳輸是一件耗時的工作,需要異步接收
var http = require(‘http‘);
var querystring = require(‘querystring‘);

http.createServer(function(req, res){
    // 定義了一個post變量,用於暫存請求體的信息
    var post = ‘‘;     

    // 通過req的data事件監聽函數,每當接受到請求體的數據,就累加到post變量中
    req.on(‘data‘, function(chunk){    
        post += chunk;
    });

    // 在end事件觸發後,通過querystring.parse將post解析為真正的POST請求格式,然後向客戶端返回。
    req.on(‘end‘, function(){    
        post = querystring.parse(post);
        res.end(util.inspect(post));
    });
}).listen(3000);

  八、全局對象

  • node 中的全局對象名為 global,瀏覽器中的全局對象名為 window
  • 務必通過 var 來定義變量,因為未定義直接賦值的變量(隱式變量)會被視為全局變量;
  • __filename, __dirname,
  • setTimeout(cb, ms), clearTimeout(t), setInterval(cb, ms)
  • console: log, info, error, warn, dir, time, timeEnd, trace, assert

當 console.log 接收到多個參數時,會進行格式化輸出:

console.log(‘Hello world‘);  // Hello world
console.log(‘byvoid%diovyb‘); // byvoid%diovyb 
console.log(‘byvoid%diovyb‘, 1991);  //byvoid1991iovyb 
  • process 屬性: stdout, stderr, stdin, argv, execPath, execArgv, env, config, pid, title
  • process 方法: abort, chdir, cwd, exit, getgid, setgid, getuid, setdui, kill, uptime …

九、Node.js常用工具

  1. util.inherits: 實現js對象間的原型繼承
  2. util.inspect: 將任意對象轉換為字符串
  3. util.isArray(object)
  4. util.isData(obj)
  5. OS,Path,net ,dns,domain

十、文件系統

var fs = require("fs");

fs.readFile("filename", (err, data)=> {
    console.log("read file");
})

  

  • fs.open(path, flags[, mode], callback)
  • fs.stat(path, callback)
  • fs.writeFile(file, data[, options], callback)
  • fs.read(fd, buffer, offset, length, position, callback)
  • fs.close(fd, callback)
  • fs.ftruncate(fd, len, callback)
  • fs.unlink(path, callback) : 刪除文件
  • fs.mkdir(path[, mode], callback)
  • fs.readdir(path, callback)
  • fs.rmdir(path, callback)

十一、Express框架

Express 是一個簡潔而靈活的應用框架。

var express = require(‘express‘);
var app = express();

app.get(‘/‘, function (req, res) {
   res.send(‘Hello World‘);
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("應用實例,訪問地址為 http://%s:%s", host, port)

})

  11.1、Request對象

  1. req.app : 訪問 express 實例
  2. req.baseUrl
  3. req.body/req.cookies
  4. req.fresh/req.stale
  5. req.hostname/req.ip
  6. req.originalUrl
  7. req.params
  8. req.path
  9. req.protocol
  10. req.query
  11. req.route
  12. req.subdomains
  13. req.accepts()
  14. req.acceptsCharsets/req.acceptsEncodings/req.acceptsLanguages
  15. req.get() : 獲取指定的 HTTP 請求頭

11.2、 Response對象

    1. res.app
    2. res.append()
    3. res.set()
    4. res.cookie(name, value [, option])
      5.
    5. res.clearCookie()
    6. res.download()
    7. res.get()
    8. res.json()
    9. res.jsonp()
    10. res.location()
    11. res.redirect()
    12. res.render(view, [locals], callback)
    13. res.send()
    14. res.sendFile()
    15. res.set()
    16. res.status()
    17. res.type()

 11.3、路由

var express = require(‘express‘);
var app = express();

//  主頁輸出 "Hello World"
app.get(‘/‘, function (req, res) {
   console.log("主頁 GET 請求");
   res.send(‘Hello GET‘);
})


//  POST 請求
app.post(‘/‘, function (req, res) {
   console.log("主頁 POST 請求");
   res.send(‘Hello POST‘);
})

//  /del_user 頁面響應
app.get(‘/del_user‘, function (req, res) {
   console.log("/del_user 響應 DELETE 請求");
   res.send(‘刪除頁面‘);
})

//  /list_user 頁面 GET 請求
app.get(‘/list_user‘, function (req, res) {
   console.log("/list_user GET 請求");
   res.send(‘用戶列表頁面‘);
})

// 對頁面 abcd, abxcd, ab123cd, 等響應 GET 請求
app.get(‘/ab*cd‘, function(req, res) {   
   console.log("/ab*cd GET 請求");
   res.send(‘正則匹配‘);
})


var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("應用實例,訪問地址為 http://%s:%s", host, port)

})

  11.4、靜態文件

可以使用 express.static 中間件來設置靜態文件路徑:

app.use(express.static(‘public‘));

 11.5、文件上傳

 

html>
<head>
<title>文件上傳表單</title>
</head>
<body>
<h3>文件上傳:</h3>
選擇一個文件上傳: <br />
<form action="/file_upload" method="post" enctype="multipart/form-data">
<input type="file" name="image" size="50" />
<br />
<input type="submit" value="上傳文件" />
</form>
</body>
</html>

  服務端代碼:

var express = require(‘express‘);
var app = express();
var fs = require("fs");

var bodyParser = require(‘body-parser‘);
var multer  = require(‘multer‘);

app.use(express.static(‘public‘));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(multer({ dest: ‘/tmp/‘}).array(‘image‘));

app.get(‘/index.htm‘, function (req, res) {
   res.sendFile( __dirname + "/" + "index.htm" );
})

app.post(‘/file_upload‘, function (req, res) {

   console.log(req.files[0]);  // 上傳的文件信息

   var des_file = __dirname + "/" + req.files[0].originalname;
   fs.readFile( req.files[0].path, function (err, data) {
        fs.writeFile(des_file, data, function (err) {
         if( err ){
              console.log( err );
         }else{
               response = {
                   message:‘File uploaded successfully‘, 
                   filename:req.files[0].originalname
              };
          }
          console.log( response );
          res.end( JSON.stringify( response ) );
       });
   });
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("應用實例,訪問地址為 http://%s:%s", host, port)

})

  12.6、 cookie管理

可以使用中間件向 Node.js 服務器發送 cookie 信息,以下代碼輸出了客戶端發送的 cookie 信息:

var express      = require(‘express‘)
var cookieParser = require(‘cookie-parser‘)
var util = require(‘util‘);

var app = express()
app.use(cookieParser())

app.get(‘/‘, function(req, res) {
    console.log("Cookies: " + util.inspect(req.cookies));
})

app.listen(8081)

  十二、數據庫

nodejs知識結構