Node.js基本使用(超基礎)

Node.js是什麼

  • Node.js是一個可以在服務器端運行JavaScript的開放源代碼、跨平臺JavaScript運行環境
  • Node採用Google開發的V8引擎運行js代碼,使用事件驅動、非阻塞和異步I/O模型等技術來提升性能,可優化應用程序的傳輸量和規模。html

  • Node大部分基本模塊都用JavaScript編寫。在Node出現以前,JS一般做爲客戶端程序設計語言使用,以JS寫出的程序常在用戶的瀏覽器上運行。node

  • Node主要用於編寫像Web服務器同樣的網絡應用,這和PH 和Python是相似的。算法

  • 可是Node與其餘語言最大的不一樣之處在於,PHP等語言是阻塞的而Node是非阻塞的。npm

  • Node是事件驅動的。開發者能夠在不使用線程的狀況下開發出一個可以承載高併發的服務器。其餘服務器端語言難以開發高併發應用,並且即便開發出來,性能也不盡人意。編程

  • Node把JS的易學易用和Unix網絡編程的強大結合到了一塊兒。
  • Node.js容許經過JS和一系列模塊來編寫服務器端應用和網絡相關的應用。json

  • 核心模塊包括文件系統I/O、網絡(HTTP、TCP、UDP、DNS、TLS/SSL等)、二進制數據流、加密算法、數據流等等。Node模塊的API形式簡單,下降了編程的複雜度。後端

  • 使用框架能夠加速開發。經常使用的Node框架有Express.js、Socket.IO和Connect等。Node.js的程序能夠在Microsoft Windows、Linux、Unix、Mac OS X等服務器上運行。api

  • Node.js也可使用CoffeeScript、TypeScript、Dart語言,以及其餘可以編譯成JavaScript的語言編程。

Node的用途

  • Web服務API,好比REST跨域

  • 實時多人遊戲數組

  • 後端的Web服務,例如跨域、服務器端的請求

  • 基於Web的應用

  • 多客戶端的通訊,如即時通訊

node目錄結構

COMMONJS規範 

  • CommonJS是一種規範,NodeJS是這種規範的實現。
  • CommonJS規範的提出,主要是爲了彌補當前JavaScript沒有模塊化標準的缺陷。

    • ECMAScript標準的缺陷 
      • 沒有模塊系統
      • 標準庫較少
      • 沒有標準接口
      • 缺少管理系統
    • 模塊化 
      • 若是程序設計的規模達到了必定程度,則必須對其進行模塊化。
      • 模塊化能夠有多種形式,但至少應該提供可以將代碼分割爲多個源文件的機制。
      • CommonJS 的模塊功能能夠幫咱們解決該 問題。
  • CommonJS規範爲JS指定了一個美好的願景,但願JS可以在任何地方運行。

  •  CommonJS對模塊的定義十分簡單: 

    • 模塊引用

      • 在規範中,定義了require()方法,這個方法接手模塊標識,以此將一個模塊引入到當前運行環境中。
      • var fs = require('fs')
    • 模塊定義

      • 在運行環境中,提供了exports對象用於導出當前模塊的方法或者變量,而且它是惟一的導出的出口。
      • 在模塊中還存在一個module對象,它表明 模塊自身,而exports是module的屬性。
      • 在Node中一個文件就是一個模塊。
      • exports.add = function(){ };
    • 模塊標識

      • 模塊標識就是傳遞給require方法的參數,必須符合小駝峯命名的字符串,或者以.、..開頭的相對路徑,或者絕對路徑。它能夠沒有文件名後綴.js。
      • 模塊的定義十分簡單,接口也十分簡潔。 每一個模塊具備獨立的空間,它們互不干擾, 在引用時也顯得乾淨利落。

包 package 

  • CommonJS的包規範容許咱們將一組相關的模塊組合到一塊兒,造成一組完整的工具。
  • CommonJS的包規範由包結構和包描述文件兩個部分組成。 

包結構

  • 用於組織包中的各類文件
  • 包實際上就是一個壓縮文件,解壓之後還原爲符合規範的目錄,應該包含如 下文件:
    • package.json --- 描述文件 
    • bin --- 可執行二進制文件
    • lib --- js代碼
    • doc --- 文檔
    • test --- 單元測試

包描述文件 

  • 描述包的相關信息,以供外部讀取分析
  • 包描述文件用於表達非代碼相關的信息,它是一個JSON格式的文件 – package.json,位於包的根目錄下,是包的重要組成部分
  • package.json中的字段 
    • name:必須,npm包的名稱
    • version:必須,版本號
    • main:用於描述npm包項目的主要入口文件。
      • 好比包名稱爲 foo ,package.json中的main字段爲foo時,當別人經過npm下載並安裝了這個包,可直接經過 require('foo') 引入這個包。
    • dependencies:這個包須要的依賴項

 NPM(Node Package Manager) 

  • CommonJS包規範是理論,NPM是其中一種實踐。 
  • 對於Node而言,NPM幫助其完成了第三方模塊的發佈、安裝和依賴等。藉助NPM, Node與第三方模塊之間造成了很好的一個生態系統。

NPM經常使用命令

  • npm –v --- 查看版本 
  • npm search 包名 --- 搜索模塊包 
  • npm install 包名 --- 在當前目錄安裝包
  • npm install 包名 –g --- 全局模式安裝包
  • npm remove 包名 --- 刪除一個模塊
  • npm install 文件路徑 --- 從本地安裝 
  • npm install 包名 –registry=地址  --- 從鏡像源安裝 
  • npm config set registry 地址 --- 設置鏡像源

module(模塊)

  • 在Node中,一個js文件就是一個模塊
  • 在Node中,每個js文件中的js代碼都是獨立運行在一個函數中(非全局做用域),因此一個模塊的中的變量和函數在其餘模塊中沒法訪問
  • 若是想要在其餘模塊訪問另外一個模塊的變量,要將須要該變量或方法設置爲exports的屬性
  • module表明的是當前模塊自己

模塊封裝器

  • 在執行模塊代碼以前,Node.js 會使用一個以下的函數封裝器將其封裝:
    (function(exports, require, module, __filename, __dirname) { // 頂部添加該行
    // 模塊實際代碼
    }); // 底部添加該行
  • 所以,在模塊中使用 var a = 123; 聲明的變量都是局部變量,緣由以下
    function(exports, require, module, __filename, __dirname) {
        var a = 123;  // 局部變量
        b = '你好';  // 全局變量 

module.require()

  • 在node中,經過require()函數來引入外部的模塊
  • require()能夠傳遞一個文件的路徑做爲參數,node將會自動根據該路徑來引入外部模塊。若是使用相對路徑,必須以.或..開頭
  • 使用require()引入模塊之後,該函數會返回一個對象,這個對象表明的是引入的模塊
    var math = require("./math"); // 使用相對路徑引入外部模塊
    var fs = require("fs"); // 使用模塊標識引入外部模塊

module.exports

  • 該對象用來將變量或函數暴露到外部
  • 既可使用  exports 也可使用  module.exports 導出變量或函數
    // module1.js
    exports.a = "123"
    // module2.js
    var module1 = require('./module1.js')
    console.log(module1)
    // 運行module2.js,可輸出123

Buffer(緩衝器)

  • 從結構上看Buffer很是像一個數組,它的元素爲16進制的兩位數。 
  • 數組中不能存儲二進制的文件,而buffer就是專門用來存儲二進制數據的
  • 實際上一個Buffer中的元素就表示內存中的一個字節。
  • Buffer中的內存不是經過JavaScript分配的,而是在底層經過C++申請的。它是對底層內存的直接操做,其大小一旦肯定則不能修改
  • 咱們能夠直接經過Buffer來建立內存 中的空間。
  • 使用buffer不須要引入模塊,直接使用便可在buffer中存儲的都是二進制數據,可是在顯示時都是以16進制的形式顯示,buffer中每個元素的範圍是從00 - ff (即二進制中的:00000000 - 11111111)

使用Buffer保存字符串

  • Buffer.from(string[, encoding])
    • string --- 要編碼的字符串
    • encoding --- string的字符編碼,默認值爲‘utf-8’
var str =  "abc";
var buf = Buffer.from(str , "utf-8");

  console.log(buf.length); // 佔用內存的大小 --- 3
  console.log(str.length);// 字符串的長度 --- 3
  console.log(buf); // Buffer --- <Buffer 61 62 63>

建立指定大小的Buffer對象

//建立一個10個字節的buffer
var buf1 = new Buffer(10); // buffer構造函數不推薦使用的
var buf2 = Buffer.alloc(10); // 推薦使用

// 能夠經過索引操做Buffer中的元素
  buf2[0] = 88;
 

Buffer的轉換

  • 將字符串轉換爲Buffer
    • Buffer.from(str)
  • Buffer轉字符串
    • buf.toString([encoding] , [start] , [end]);

寫入操做

  • 向緩衝區中寫入字符串
    • buf.write(string[, offset[, length]][, encoding])
  • 替換指定索引位置的數據
    • buf[index]
  • 將指定值填入到緩衝區的指定位置
    • buf.fill(value[, offset[, end]][, encoding])

讀取操做

  • 將緩衝區中的內容,轉換爲一個字符串返回 
    • buf.toString([encoding[, start[, end]]])
  • 讀取緩衝區指定索引的內容 
    • buf[index]

其餘操做

  • 複製緩衝區  buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
  • 對緩衝區切片  buf.slice([start[, end]])
  • 拼接緩衝區  Buffer.concat(list[, totalLength])

fs(文件系統) 

  • 在Node中,與文件系統的交互是很是重要的,服務器的本質就將本地的文件發送給遠程的客戶端
  • Node經過fs模塊來和文件系統進行交互
  • 該模塊提供了一些標準文件訪問API來打開、讀取、寫入文件,以及與其交互
  • 簡單的說,文件系統就是經過Node來操做系統中的文件
  • 使用文件系統,須要先引入fs模塊,fs是核心模塊,能夠直接引入不須要下載 var fs = require('fs')

同步和異步調用

  • fs模塊中全部的操做都有兩種形式可供選擇同步異步
  • 同步文件系統會阻塞程序的執行,除非操做完畢,不會向下執行代碼。 效率較低。
  • 異步文件系統不會阻塞程序的執行,它會在操做完成時,經過回調函數將結果返回。

同步文件寫入

  • 同步打開文件  fs.openSync(path, flags[, mode])
    • 該方法會返回一個文件的描述符做爲結果,咱們能夠經過該描述符來對文件進行各類操做
    • 參數
      • path:要打開文件的路徑
      • flags:打開文件要作的操做的類型
      • mode:設置文件的操做權限,通常不傳
  • 同步寫入內容 fs.writeSync(fd, string[, position[, encoding]])
    • 參數
      • fd:文件的描述符,須要傳遞要寫入的文件的描述符
      • string:要寫入的內容
      • position:寫入的起始位置
      • encoding:寫入的編碼,默認utf-8
  • 保存並關閉文件  fs.closeSync(fd) 
    • 參數
      • fd:文件的描述符,須要傳遞要寫入的文件的描述符
var fs = require("fs");

//打開文件
var fd = fs.openSync("hello.txt" , "w");

//向文件中寫入內容
fs.writeSync(fd , "12345678", 2);

//關閉文件
fs.closeSync(fd);

異步文件寫入

注:異步調用的方法,結果都是經過回調函數的參數返回的

  • 異步打開文件 fs.open(path, flags[, mode], callback)
    • 回調函數的兩個參數
      • err:錯誤對象,若是沒有錯誤則爲null
      • fd:文件的描述符
  • 異步寫入文件 fs.write(fd, string[, position[, encoding]], callback) 
  • 異步關閉文件  fs.close(fd, callback) 
var fs = require("fs");

//打開文件
fs.open("hello2.txt","w",function (err , fd) {
    //判斷是否出錯
    if(!err){
        //若是沒有出錯,則對文件進行寫入操做
        fs.write(fd,"這是異步寫入的內容",function (err) {
            if(!err){
                console.log("寫入成功");
            }
            //關閉文件
            fs.close(fd , function (err) {
                if(!err){
                    console.log("文件已關閉");
                }
            });
        });
    }else{
        console.log(err);
    }
});

簡單文件寫入

  • 同步  fs.writeFileSync(file, data[, options]) 
  • 異步  fs.writeFile(file, data[, options], callback) 
  • 參數
    • file:要操做的文件的路徑
    • data:要寫入的數據
    • options 選項:能夠對寫入進行一些設置
      • flag
        • r 只讀
        • w 可寫
        • a 追加
var fs = require("fs");

fs.writeFile("hello.txt","這是經過writeFile寫入的內容",{flag:"w"} , function (err) {
    if(!err){
        console.log("寫入成功~~~");
    }else{
        console.log(err);
    }
});

流式文件寫入

  • 同步、異步、簡單文件的寫入都不適合大文件的寫入,性能較差,容易致使內存溢出,可寫流適合大文件的寫入
  • 建立一個可寫流  fs.createWriteStream(path[, options])
    • path:文件路徑
    • options:配置的參數
  • 能夠經過監聽流的open和close事件來監聽流的打開和關閉  ws.once("open",function () { console.log("流打開了"); }); 
var fs = require("fs");

var ws = fs.createWriteStream("hello3.txt"); // 建立一個可寫流

ws.once("open",function () { // 監聽流的打開
    console.log("流打開了");
});

ws.once("close",function () { // 監聽流的關閉
    console.log("流關閉了");
});

ws.write("經過可寫流寫入文件的內容"); // 寫入內容

ws.end(); // 關閉流

文件的讀取

  • 同步文件讀取(略)
  • 異步文件讀取(略)
  • 簡單文件讀取(略)
    • 異步:  fs.readFile(path[, options], callback) 
    • 同步: fs.readFileSync(path[, options]) 
    • 參數
      • path:要讀取的文件的路徑
      • options:讀取的選項
      • callback:回調函數,經過回調函數將讀取到內容返回(err , data)
        • err:錯誤對象
        • data:讀取到的數據,會返回一個Buffer
var fs = require("fs");

var path = "C:/Users/lilichao/Desktop/筆記.mp3";

fs.readFile("an.jpg" , function (err , data) {
    if(!err){
        //console.log(data);
        //將data寫入到文件中
        fs.writeFile("C:/Users/lilichao/Desktop/hello.jpg",data,function(err){
            if(!err){
                console.log("文件寫入成功");
            }
        } );
    }
});

流式文件的讀取

// 流式文件讀取也適用於一些比較大的文件,能夠分屢次將文件讀取到內存中

var fs = require('fs');

var rs = fs.createReadStream('b.mp3')
var ws = fs.createWriteStream('a.mp3')

rs.once('open', function () {
    console.log('可讀流打開了')
})

rs.once('close', function () {
    console.log('可讀流關閉了')
    // 數據讀取完畢,關閉可寫流
    ws.end()
})

ws.once('open', function () {
    console.log('可寫流打開了')
})

ws.once('close', function () {
    console.log('可寫流關閉了')
})

// pipe 可把可讀流中的內容直接輸出到可寫流中
rs.pipe(ws);
相關文章
相關標籤/搜索