在我印象裏,「全棧工程師」這個詞是NodeJS誕生後才逐漸火起來的,由於NodeJS賦予了JS服務器開發的能力。下面開始從一個小白的角度進軍NodeJS...php
前言:在學習NodeJS以前是須要安裝的,安裝方法很easy。安裝好以後,安裝路徑會自動寫到環境變量path路徑中,因此咱們能夠直接cmd去黑窗口用node命令運行js文件。html
Node.js是一個構建在Chrome V8引擎上的 JavaScript 運行環境。java
此時,JS的運行環境就多了一個,變成倆個了——瀏覽器、NodeJS。安裝完node以後,咱們就能夠用node命令去執行js文件。好比node demo.js命令去執行一個demo.js文件...node
單線程、非阻塞異步I/O、事件驅動 web
也就是說,同一個時間只能作一件事,不像java、php那樣能夠建立多個線程,這是js的特色。express
在Java、PHP或者.net等服務器語言中,會爲每一個客戶端鏈接建立一個新的進程。而每一個進程須要耗費大約2MB內存。也就是說,理論上一個8GB的服務器能夠同時鏈接最大用戶量爲4000個左右。要讓Web應用程序同時支持更多的用戶,就須要增長服務器的數量或內存數,這樣硬件成本就上升了。npm
NodeJS不爲每一個客戶鏈接建立一個新的線程,而僅僅使用一個線程。當有用戶鏈接,就觸發一個內部事件,經過非阻塞I/0、事件驅動機制,讓NodeJS程序宏觀上也是並行的,給人的感受就是用戶之間互不影響。使用NodeJS,一個8GB內存服務器,能夠同時處理超過4萬用戶的鏈接。編程
另外,單線程帶來的好處還有操做系統徹底再也不有線程建立、銷燬的時間開銷。json
簡單點說就死異步不會阻塞後面的代碼。絕大多數網站的I/O操做不少,I就是input數據的讀取,O就是output數據的寫入。可是I/O的時候,CPU命令磁盤去作事情,CPU就閒置了。瀏覽器
主線程:主線程會一直輪詢,隊列中沒有代碼了,主線程就會退出。
1.執行node的代碼,把代碼放入隊列
2.事件循環程序(主線程)把隊列裏面的同步代碼都先執行了,
3.同步代碼執行完成,執行異步代碼
4.異步代碼分2種情況,
1.異步非io setTimeout() setInterval(),判斷是否可執行,若是能夠執行就執行,不能夠跳過。
2.異步io 文件操做 會從線程池當中去取一條線程,幫助主線程去執行。
子線程:被放在線程池裏面的線程,用來執行異步io操做
1.在線程池裏休息
2.異步io的操做來了,執行異步io操做。
3.子線程會把異步io操做的callback函數,扔回給隊列
4.子線程會回到線程池了去休息。
回調(callback ):在異步io代碼執行完成的時候被扔回主線程。
1. 引入 required 模塊:咱們可使用 require 指令來載入 Node.js 模塊。
2. 建立服務器:服務器能夠監聽客戶端的請求,相似於 Apache 、Nginx 等 HTTP 服務器。
3. 接收請求與響應請求:服務器很容易建立,客戶端可使用瀏覽器或終端發送 HTTP 請求,服務器接收請求後返回響應數據。
// 使用 require 指令來載入 http 模塊,並將實例化的 HTTP 賦值給變量 http var http = require('http'); // 使用 http.createServer() 方法建立服務器,並使用 listen 方法綁定 3000端口。 函數經過 request, response 參數來接收和響應數據 http.createServer(function (request, response) { // 發送 HTTP 頭部 // HTTP 狀態值: 200 : OK // 內容類型: text/plain response.writeHead(200, {'Content-Type': 'text/plain'}); // 發送響應數據 "Hello World" response.end('Hello World\n'); }).listen(3000); // 終端打印以下信息 console.log('Server running at http://127.0.0.1:3000/');
把以上代碼放到單獨某個js文件中,用node命令去執行,便會在本地建立一個端口號爲3000的服務器。
NPM是隨同NodeJS一塊兒安裝的包管理工具,能解決NodeJS代碼部署上的不少問題,常見的使用場景有如下幾種:
-- 容許用戶從NPM服務器下載別人編寫的第三方包到本地使用。
-- 容許用戶從NPM服務器下載並安裝別人編寫的命令行程序到本地使用。
-- 容許用戶將本身編寫的包或命令行程序上傳到NPM服務器供別人使用。
一、使用npm命令安裝模塊 : $ npm install <Module Name>
好比:npm 命令安裝經常使用的 Node.js web框架模塊 express: $ npm install express 安裝好以後,express 包就放在了工程目錄下的 node_modules 目錄中。所以在代碼中只須要經過 require('express') 的方式就好,無需指定第三方包路徑。引用方式: var express = require('express');
二、全局安裝和本地安裝:npm 的包安裝分爲本地安裝(local)、全局安裝(global)兩種,從敲的命令行來看,差異只是有沒有-g而已,好比:
npm install express # 本地安裝
npm install express -g # 全局安裝
本地安裝
1. 將安裝包放在 ./node_modules 下(運行 npm 命令時所在的目錄),若是沒有 node_modules 目錄,會在當前執行 npm 命令的目錄下生成 node_modules 目錄。
2. 能夠經過 require() 來引入本地安裝的包。
全局安裝
1. 將安裝包放在 /usr/local 下或者你 node 的安裝目錄。
2. 能夠直接在命令行裏使用。
三、建立模塊,package.json 文件是必不可少的。咱們可使用 NPM 生成 package.json 文件
Node.js 異步編程的直接體現就是回調。
異步編程依託於回調來實現,但不能說使用了回調後程序就異步化了。
回調函數在完成任務後就會被調用,Node 使用了大量的回調函數,Node 全部 API 都支持回調函數。
例如,咱們能夠一邊讀取文件,一邊執行其餘命令,在文件讀取完成後,咱們將文件內容做爲回調函數的參數返回。這樣在執行代碼時就沒有阻塞或等待文件 I/O 操做。這就大大提升了 Node.js 的性能,能夠處理大量的併發請求。
回調函數通常做爲函數的最後一個參數出現:
function foo1(name, age, callback) { }; function foo2(value, callback1, callback2) { }
阻塞代碼實例:
// 引入文件操做模塊 var fs = require("fs"); var data = fs.readFileSync('input.txt'); //input.txt內容是: 我是input.txt內容 console.log(data.toString()); console.log("程序執行結束!"); // 用node命令執行 $ node main.js 我是input.txt內容 程序執行結束!
非阻塞代碼實例:
// 引入文件操做模塊 var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
if (err) return console.error(err); console.log(data.toString());
});
console.log("程序執行結束!");
// 用node命令執行
$ node main.js
程序執行結束!
我是input.txt內容
第一個實例在文件讀取完後才執行完程序。
第二個實例咱們不須要等待文件讀取完,這樣就能夠在讀取文件時同時執行接下來的代碼,大大提升了程序的性能。
所以,阻塞是按順序執行的,而非阻塞是不須要按順序的,因此若是須要處理回調函數的參數,咱們就須要寫在回調函數內。