面向前端工程師的Nodejs入門手冊(一)

前言

本文面向的讀者已是瞭解JavaScript基本使用的前端程序員,可是缺少服務端的經驗,接下來將帶你走進在服務端的世界,看看運行在服務端的JavaScript是如何工做的,它與運行在瀏覽器端的JavaScript有何異同,相比於瀏覽器能多作哪些事情,有何優點。javascript



文章經過實例的方式,讓你瞭解Nodejs可以作什麼,能夠解決一些什麼樣的問題,而且知道它的使用場景。若是你有興趣,請記住必定要本身動手,哪怕照着實例寫一遍,真真實實的感覺代碼運行時的喜悅與興奮,激發本身對新領域的興趣。html

默認你已經安裝了Nodejs和npm包管理器,而且熟悉一些簡單的操做,如nodejs代碼的運行啓動,npm包的安裝命令等基礎操做。前端

第一個服務端應用

1.hello world java


首先經過一個前端工程師最常接觸卻不屬於前端範疇的內容去了解一下Nodejs,建立一個http服務。這裏使用Nodejs自帶的http模塊建立一個http服務,你可使用經過瀏覽器或者命令行來發起一個http請求,直觀的感覺服務端的JavaScript。node

// http.js
const http = require('http');

http.createServer((req, res) => {
  res.end('Hello World!');
}).listen(8000, ()=> {
  console.log('listen on 8000!');
})複製代碼
複製代碼

上面的例子中,經過使用node自帶的http模塊,調用其http.creatServer方法在本機上開啓了一個http服務,監聽了本地的8000端口,代碼邏輯很簡單,當接收到一個req請求時,調用res.end返回一個字符串"hello world"給帶客戶端,旨在讓你對Nodejs有一個直觀的體驗。ios


可使用node http.js命令來執行這段代碼,經過瀏覽器來訪問http://127.0.0.1:8000或者http://localhost:800來查看結果。git


一個由Nodejs的http服務提供的hello world跑起來了,簡潔快速吧。接下來再來實現一個前端工做中與服務端最緊密的內容來看看Nodejs的魅力,數據接口。程序員


2. 如何提供一個API github


首先這裏肯定所要提供的api是咱們最經常使用的json格式,因此咱們要注意後端返回給前端的數據類型。ajax

const http = require('http');

const data = {
  name: 'Nodejs 入門示例',
  description: '這是返回信息的描述內容',
  date: new Date()
};

http.createServer((req, res) => {
  res.setHeader('Content-Type', 'application/json;charset=utf-8');
  const result = JSON.stringify(data);
  res.end(result);
}).listen(8000, ()=> {
  console.log('listen on 8000!');
})複製代碼

上例子中,先肯定了一個數據模型data,內部一共有三個字段。這裏的數據模型就是前端開發前與後端所定義的返回格式,最終前端要拿到這個JSON格式的數據在客戶端進行處理。代碼邏輯相比於Hello World,規定了返回的數據格式,以及設定了返回請求的文本類型爲application/json,而後調用res.end返回到客戶端。



能夠繼續使用瀏覽器發起http請求來查看結果,一個簡單且熟悉的JSON數據接口已經完成了。你能夠按照前端最經常使用的調用方式,如ajax或者axios來請求接口來在你的前端項目使用它。

可是上面例子中的接口和咱們經常使用的接口有一個差別點,就是接口名稱和返回內容均不規範,使用者直接經過沒有路徑的http://127.0.0.1:8000來使用接口,這跟咱們平常使用的接口是徹底不同的,那咱們接下來再看一下如何給提供一個規範化的接口呢?


3.一個規範的接口


規範的接口具有哪些條件呢?簡單總結一下。

接口名稱:接口名稱要體現出大體的使用場景,例如增刪改查的動做。

接口返回:接口返回要有規範化的標識,如成功與否錯誤內容等。


接下來經過上面這兩個點,按照標準的接口規範來實現一下上面的接口,看看Nodejs是如何給前端提供接口的。這裏先約定要提供的接口名稱內含api標誌,api所要作的動做等一些關鍵信息。以下格式:


http://localhost:8000/api/search/data?userId=12345

const http = require('http');
const url = require('url');
const qs = require('querystring');

// 生成一段返回值
const genResponse = userId => ({
  success: true,
  data: {
    userId,
    name: 'Nodejs 入門示例',
    description: '這是返回信息的描述內容',
    date: new Date()
  }
});

// http服務
http.createServer((req, res) => {
  res.setHeader('Content-Type', 'application/json;charset=utf-8');
  const reqUrl = url.parse(req.url);
  // 判斷接口路徑是不是約定好的
  if (reqUrl.pathname === '/api/search/data') {
    // 獲取連接上傳來的userId參數
    const uid = qs.parse(reqUrl.query).userId;
    // 生成返回值
    const result = JSON.stringify(genResponse(uid));
    res.end(result);
  } else {
    res.writeHead(404);
    res.end('NotFund');
  }
}).listen(8000, ()=> {
  console.log('listen on 8000!');
})
複製代碼


上面的例子中,新使用Nodejs另外一個自帶的模塊url,url模塊顧名思義是一個處理href的庫,它將href拆分紅各個子內容,同時爲了能處理客戶端帶來的userId參數還使用了自帶的querystring模塊,它能夠將連接上問號後的query參數獲取到,以便服務端代碼能使用他們,他們均屬於工具庫,下面看看官方對於URL模塊將href拆分的顆粒度圖,清晰的瞭解一下一個請求連接,能夠被拆分紅什麼顆粒度。



實例中的源碼簡單解析一下,當服務接收到請求時,先判斷請求的api名稱是否是事先約定好的/api/search/data,判斷經過後,將前端傳遞在連接上的參數userId獲取到,處理後插入到返回的json數據中,便可經過res.end來下發數據,若是路徑判斷失敗,則返回404的狀態碼,而且進入Notfund頁面,


一個規範的接口已經開發完成了,簡單總結一下,上面以漸進式的方式瞭解了Nodejs如何給前端來提供一個規範化的http接口,瞭解了服務端的JavaScript所具有的能力,接下來再從另外一個前端工程師比較少接觸的內容——文件操做,來進一步瞭解Nodejs。


文件操做那些事

對於文件操做相關的內容,前端程序員通常是不會觸及的,並且JavaScript語言自己也並無暴露操做文件的方法。而在Nodejs中,自己便提供了fs文件操做模塊,這個模塊模塊底層並非JavaScript來編寫的,是具有操做文件的C++語言編寫的,其封裝完成後將上層暴露給Nodejs,而後即可以使用JavaScript的語法來調用它。


1.讀一個文件

在Nodejs中,讀文件有兩種形式,一種是同步的另外一種是異步的,同步能夠理解爲讀文件這個過程要等待,就是一旦執行的讀這個操做的時候,你的代碼就被」卡「住了,直到文件讀完才能繼續執行,來看看下面的例子。

先新增一個test.md文件配合讀操做,文件內容爲:### 我是一個文件

// fsread.js
const fs = require('fs');

const file = fs.readFileSync('./test.md', 'utf8');

console.log(file);複製代碼


使用node fsread.js來運行上面的代碼,從上面簡單的幾行你就能夠發現成功將test.md文件裏的內容讀出來,能夠打印到了命令行console裏,忽然發現JavaScript語言的強大了吧,很神奇吧。


可是Nodejs天生是爲異步而生的,因此必需要體驗一下異步讀文件是怎麼的過程,與同步的表現有何異同。因此 下面示例一個異步回調的方式去讀一個文件,異步的意思就是讀文件這個操做進行的同時,讀操做下面的JavaScript代碼也在執行,就如同咱們熟悉的軟件後臺運行同樣,你能夠繼續你的桌面操做。

const fs = require('fs');

console.log('sync start');

fs.readFile('./test.md', 'utf8', (err, data) => {
  console.log('test.md 的內容');
  console.log(data);
});

console.log('sync progress');

fs.readFile('./test2.md', 'utf8', (err, data) => {
  console.log('test2.md 的內容');
  console.log(data);
});

console.log('sync finish');複製代碼
複製代碼

在上面的例子中,要求是一次讀取兩個文件,兩個文件之間並無相關依賴性,因此這種 場景下咱們更但願他們各作各的,無需去等。因此沒有必要像上面同步的方式,等第一個結束再進入第二個的讀取,因此使用異步方式更合適。



從上面的執行結果也能夠看出來,fs.readFile這個異步回調操做均在三個同步代碼 console的後面,並無像同步等待讀操做的結束。


下面來個圖看看這個同步API和異步API有何異同。



圖片上半部分是異步讀文件,能夠看出來,讀的操做能夠理解爲同時刻執行的。

圖片下半部分是同步讀文件,第二個讀的操做須要先等待第一個讀完才能夠。

舉個現實生活中同步的場景,運動會接力賽,A,B兩個班比賽接力,雖然A,B兩個班無依賴,可是A班的第二名同窗則須要第一名同窗的接力棒拿到後纔可繼續跑,此時A班的運動員之間就屬於同步阻塞類型。

在舉個異步的場景,老闆經過全員會議下達了一個任務,任務是你們作一百個俯臥撐,誰先作完任務則能夠領取10000元紅包的獎勵,你們聽到後紛紛原地作起,在這時候各個員工之間就是異步的,他們各作各的,誰先作完就能夠執行老闆給他們的開始說的領取獎勵操做,這個操做能夠理解爲異步回調函數。


2. 寫一個文件

Nodejs寫文件也是有兩個類型,同步與異步,實際執行流程與上面的「讀」是同樣的。

下面進入同步讀文件的例子,執行下面的代碼你會發現多了一個test3.md文件,而且寫入'### 我是測試文件test3'的內容

const fs = require('fs');

const body = '### 我是測試文件test3的內容';
fs.writeFileSync('./test3.md', body);複製代碼

再來看一下異步寫一個文件的例子,作一個對比。

// 來一個異步的看看。
const fs = require('fs');

const body = '### 我是測試文件test4的內容';
fs.writeFile('./test4.md', body, (err) => {
  if (err) throw err;
  console.log('文件test4已被保存');
});

const body2 = '### 我是測試文件test5的內容';
fs.writeFile('./test5.md', body2, (err) => {
  if (err) throw err;
  console.log('文件test5已被保存');
});複製代碼

這是寫文件的結果,這時候你的本地會多出兩個文件test4.md和test5.md出來。


3.其餘文件操做

其實Nodejs提供了豐富的文件操做接口,除了讀寫,還有像複製,給文件受權,刪除一個文件,文件夾的操做,文件內容的監聽等,若是你有對文件的操做需求,請先在文檔查一下看是否可以知足你。

文檔地址:http://nodejs.cn/api/fs.html

下面來一個文件內容監聽的例子,帶你看看一個文件變化時也能被觀察到樂趣。

const fs = require('fs');

fs.watch('./test6.md', 'utf8', (eventType, filename)=>{
  // eventType 是 'rename' 或 'change',
  // filename 是觸發事件的文件的名稱
  console.log('eventType', eventType);
  console.log('filename', filename);
});複製代碼

我將test6.md的內容進行手動的變化,而且改了名字,這裏都被監聽到了,是否是頗有趣,跟我一塊兒來練習吧。


總結

本文從前端工程師們最常接觸卻又不屬於前端領域的兩個方面,http服務與文件操做展開了學習,從幾個簡單易懂的例子帶領去了解了Nodejs。回想當初我爲何學習Nodejs,其實就是由於它的簡單便捷,幾行代碼就能作出一些我想要的效果,能快速的完成個人要求。

若是上面的入門示例也讓你對Nodejs有了濃厚的興趣,那麼請快速動手學習起來吧,看再多文章不如本身手寫一遍,從零到一,跟我一塊兒學習吧。

文章用到的代碼都可在此獲取:

https://github.com/FantasyGao/Practice-book/tree/master/nodejs


如上內容均爲本身總結,不免會有錯誤或者認識誤差,若有問題,但願你們留言指正,以避免誤人,如有什麼問題請留言,會盡力回答之。若是對你有幫助不要忘了分享給你的朋友或者點擊右下方的「在看」哦!也能夠關注做者,查看歷史文章而且關注最新動態,助你早日成爲一名全棧工程師!

相關文章
相關標籤/搜索