服務端 | Nodejs 學習筆記(一)

Node.js javascript


 

前言:
  2009年面世
  nodejs.org 官網
  https://www.npmjs.com/ 模塊社區
  github.com 倉庫
  stackoverflow.com  問答社區
  基於chrome瀏覽器V8引擎、C++語言編寫的,本質上是Js的運行環境;
  能夠解析js代碼;
  提供系統級別的api:
    一、文件的讀寫
    二、進程的管理
    三、網絡通訊java

安裝:
  linux 上安裝nodejs
  mac 上安裝node:
    升級到mac系統到最新;
    下載安裝 xcode 集成開發環境;
    xcode-select -p 檢查是否安裝了xcode 若是返回一個路徑,說明已經安裝了;若是沒有安裝
    xcode-select --install
  安裝python;
  安裝homebrew 「是針對Mac下的套件管理器,至關於ubuntu下的apt-get,至關於CentOS下的yum
    homebrew 依賴於 ruby,若是安裝不成功,嘗試升級ruby版本;
    brew install node mongodb
  node -v
  安裝 node 版本管理工具 n
  npm install -g n
    n的使用
    n 0.10.22
    n
-- 用 nodejs 建立一個服務器;
本質上是一個 javascript 的執行環境,只不過加上封裝、web底層的處理,賦予了更多的能力;
保存爲server.jsnode

 1 const http = require('http'); // 加載http模塊,這個模塊是由js編寫的;指責是建立服務器,處理 http 相關任務
 2 const hostname = '127.0.0.1';
 3 const port = 3000;
 4 const server = http.createServer((req, res) => {
 5 // 經過 createServer 建立一個web服務器,有請求從監聽的端口過來時,調用裏邊匿名的回調函數;req用來獲取此次請求相關的信息,res告訴服務器,響應一些內容;
 6   res.statusCode = 200;
 7   res.setHeader('Content-Type', 'text/plain');
 8   res.end('Hell Frank,fighting ! \n');
 9 });
10 
11 server.listen(port, hostname, () => { // 讓服務器在端口上監聽請求;服務器就 ready 了,就能夠收到任何來自3000端口的請求
12   console.log(`Server running at http://${hostname}:${port}/`);
13 });

node server.js // 執行python

瀏覽器刷新 http://127.0.0.1:3000/ jquery

 

Nodejs 環境 和 瀏覽器的執行環境的異同:linux

(1)均可以正常的執行 js 代碼
(2)宿主 瀏覽器是 window; node中沒有 window document,有process http 等模塊,可是瀏覽器沒有git

Node.js 的模塊 與 Commonjs規範:github

以前的http 和 process 都是nodejs的模塊;
頁面中有大量js引入時,尤爲是有相互依賴的狀況下,很容易被覆蓋掉,方法被重寫了,js天生缺乏一種模塊管理機制,來隔離實現不一樣功能的js片斷,避免他們相互污染;
爲此咱們常常採用命名空間的方式,把變量和函數限制到某個特定的做用域內,人肉約定一套命名規範來約束代碼,從而保障代碼的安全執行,好比jQuery中,有許多的變量和方法,必須經過$調用;
commonjs 並不像 jquery 是一套具體實現某功能的庫,他是一套規範,包括模塊、包、系統、二進制、單元測試等等,來約定 javascript 怎麼來組織,怎麼編寫,同時大部分標準也是在擬定和討論之中的;
首先把執行不一樣任務的代碼塊看作成一個獨立的模塊,每個模塊看做成一個獨立的做用域,但並非孤立的,可能存在某種依賴關係,對於一個模塊能夠分紅三個部分:模塊的定義、模塊的標示、模塊的引用;js規範。
Nodejs借鑑 commonjs 模塊組織的理念,實現了一套模塊管理系統;web

模塊的分類:
  核心模塊、本地模塊、第三方模塊;mongodb


Nodejs API

url.parse() 解析url:

  url.format()

  url.resolve()

querystring 解析參數:

  querystring.stringfy({name: 'frank', age: 19})  將參數對象序列化解析爲參數字符串,默認用=連接key alue,&;

  querystring.parse() 將參數對象反序列化;三個參數('',  ',' , ':' , 0)

  querystring.escape(str)  參數轉譯

  querystring.unescape()   參數反轉譯

http 知識填坑:

  網絡通訊協議,http客戶端發起請求,建立端口;http服務器在端口監聽客戶端請求;http服務器向客戶端返回狀態信息和內容;

  (1)瀏覽器輸入url,接下來發生了什麼。。。

  -1-、chrome瀏覽器搜索自身的DNS緩存,看看本身的DNS緩存有沒有 baidu.com 對應的ip地址緩存,或緩存有沒有過時,該緩存有效時間約 1 分鐘;

  「chrome://net-internals/#dns 可查看瀏覽器dns緩存」

  -2-、如沒有,搜索操做系統自身的DNS緩存;

  -3-、如沒有,讀取本地 host 文件,找是否有 DNS 的配置項;

  -4-、如沒有,瀏覽器發起一個 DNS 的系統調用,向寬帶運營商發起域名解析請求;

    「 寬帶運營商服務器查看自己緩存,看是否有配置項,是否過時,

    若是沒有,運營商服務器 代替瀏覽器發起一個迭代DNS解析請求 ---> 萬網等域名服務上返回 ip 地址,

    運營商服務器把返回的結果 -> 返回操做系統內核並緩存起來,操做系統內核把結果返回給瀏覽器,瀏覽器拿到了對應的ip地址,域名解析完成。    

  -5-、瀏覽器得到域名對應的 ip 地址後,發起經典的 HTTP 「三次握手」;「TODO」

  「瀏覽器向服務器發起TCP鏈接請求,經過層層路由設備到達服務器端的網卡,而後進入到服務器內核的 TCP/IP 協議棧,通過防火牆的過濾,創建起TCP/IP鏈接;」

  -6-、 創建起 TCP/IP 鏈接以後,瀏覽器就能夠向服務器發送 HTTP 請求了,

  -7-、 服務器接收請求後,根據路徑參數,通過後端的一些處理以後,把處理的結果返回給瀏覽器,瀏覽器進行渲染出頁面;

  (2)請求方法:

    GET : 讀取;POST:提交數據; PUT:更新信息;DELETE:刪除;HEAD;TRACE;

  (3)狀態碼:

    1xx : 請求已經發出,正在處理

    2xx : 成功接受 「200 客戶端請求成功」

    3xx : 須要重定向 : TODO

    4xx : 客戶端錯誤:

      400 客戶端語法等錯誤,服務器不能理解  

      401 請求沒有通過受權」「服務器收到請求,拒絕服務,多是沒有權限等」「請求資源不存在,也多是url錯了」

    5xx : 服務器端的錯誤: 「500服務器發生了不可預期的錯誤」「服務器當前不能處理該請求,可能過一段時間會恢復正常」

  (4)https 協議

    

    https 是基於 http,在 http 基礎上增長了 SSL/TLS 握手、數據加密傳輸;

    專門用於處理加密訪問;

    搭建https服務器時須要ssl證書;

    建立 https 服務器:

    

Node HTTP 模塊:

(1)回調:

  回調是異步編程最基本的方法,對於nodejs,須要按照順序執行異步邏輯時,採用後續傳遞的方式,將後續邏輯封裝在回調函數中做爲起始函數的參數,逐層嵌套;

(2)同步 異步:

  同步就是執行一個任務,後一個任務等待前一個任務完成後開始執行,程序的執行順序與任務的排列順序有關;

  js中經典的異步: setTimeout setInterval

(3)I/O  磁盤的讀入 輸出:

(4)單線程 / 多線程:

(5)阻塞 / 非阻塞:

(6)事件: 瀏覽器中鼠標的點擊,拖拽窗口,

(7)事件驅動:

(8)基於事件驅動的回調:

(9)事件循環: eventloop 是個回調函數隊列,單線程,先進先出

關於「做用域」 「上下文」  填坑:

  - 做用域:和調用函數、訪問變量的能力有關;局部做用域能夠訪問全局做用域的變量和函數,全局的訪問不到局部的;

  - 上下文: this 關鍵字有關,是調用當前可執行代碼的引用;

    「上下文表明 this 變量的值和指向,決定一個函數被怎麼調用,當一個函數被做爲一個對象的方法調用的時候,this老是指向調用這個方法的對象; 」

    「JS中,this 表示當前函數的擁有者,一般把擁有者叫做「執行上下文」;

      this 是 js 的關鍵字,是函數運行時自動生成的內部對象;只能在函數內部使用;

      對於函數的上下文執行對象,須要依據當前的運行環境而定,在全局運行的上下文中,this指向全局對象,在函數內部,this取決於函數被調用的方式:以下

                   「 this指向pat對象;」

       「 全局調用,this指向全局對象,瀏覽器:window;node環境指向 global 」

       「 構造函數中使用this,this指向新購建好的對象,實例對象;」

  JS的函數存在概念:定義時的上下文,運行時的上下文,上下文是能夠改變的。函數的方法 call()  apply() 能夠改變上下文執行對象,能夠在自定義上下文中執行函數

       「 運行時改變上下文:經過call 改變this上下文,在調用時,將 this 指向dog,實現繼承;」

       「 定義時改變上下文:這種方法不是執行是改變this指向,定義時已經改變了指向;」

event事件:

  node 事件沒有冒泡、捕獲等;

var EventEmitter =  require('events').EventEmitter

var life = new EventEmitter() life.setMaxListeners(11) // 默認監聽不超過10個,不然報 warning life.on('eventname', function (who) { // 此時 on 能夠用 addEventListener 替換   console.log('給' + who+ '倒水') }) lief.emit('eventname', '漢子') 
lief.emit('eventname', '漢子') 返回一個布爾值,true,說明事件被監聽過;

Promise

異步的解決方案:

(1)回調

(2)事件機制

(3)對事件增長事件監聽,對某個異步操做增長異步觸發,

(4)訂閱者發佈者 的 觀察者模式

(5)promise 

Promise A 與 Promise A+規範:

  

  promise庫:bluebird

 promise重構網站爬蟲:「待續」

  


 Nodejs 中的網絡模塊 - NET:

互聯網的價值基礎是數據傳送,一塊兒都圍繞數據展開,好比發送、接受等,但這一切都離不開網絡;http、https都是創建在 NET 模塊之上的;

Buffer :緩衝,在Nodejs中處理二進制的數據,Buffer的存在是由於,javascript的字符串是以 utf-8 編碼格式存儲的,處理二進制的能力是很弱的,而網絡層對於資源的存儲請求等都是以二進制的格式交互的,因此 Nodejs 就有 Buffer 這個接口,來建立專門存放二進制數據的緩存區,而且提供給了一些方法對於這些數據進行進一步的處理;

Buffer 在 Nodejs 中是能夠直接訪問的,不須要 require 來加載,Buffer 有一些靜態方法,能夠實例化,實例化以後的對象上有相應的屬性和方法;

生成實例的方法(1)new (2)傳入一個size,以字節數爲單位,傳遞給構造函數,生成一段內存區間;  (3)經過數組初始化;

(1)經過new實例化  

  

Buffer 是個對象,也是一個構造函數,具備本身的屬性和靜態方法;

經過它new出來的實例,實際上是V8引擎分配的一段內存;基本上是數組,成員都是整數值;

  

Buffer對象與字符串相互轉換過程是須要指定編碼格式的,默認是 utf-8;

  

(2)傳入一個size,以字節數爲單位,傳遞給構造函數,生成一段內存區間

    length屬性表示緩存區的大小,寫入內容超出長度的部分是不會被緩衝的,以下:

  

(3)經過數組實例化,實例化後能夠經過下標來訪問某一個值;數組的一個某一項若是爲小數,訪問到的也只是整數

  

- Buffer 實例的方法 - 

  

 - stream 流- 

    事件驅動,可控制;

  Readable 可讀流  -- > 讀取外部的數據,並吧讀到的數據緩存到內部的 Buffer 數組中;

  Writable 可寫流 -- > 負責消費數據,從可讀流中獲取數據,從獲取到的 trunk 數據塊進行處理;

  Duplex --

  Transform -- 轉換流

  eg: 

  

  定製可讀流、定製可寫流、定製轉換流,而且實現他們的內置接口;

  

  

  

相關文章
相關標籤/搜索