2万人同时访问 nodejs_面向前端工程师的Nodejs入门手册(一)
前言
本文面向的讀者已經(jīng)是了解JavaScript基本使用的前端程序員,但是缺乏服務端的經(jīng)驗,接下來將帶你走進在服務端的世界,看看運行在服務端的JavaScript是如何工作的,它與運行在瀏覽器端的JavaScript有何異同,相比于瀏覽器能多做哪些事情,有何優(yōu)勢。
文章通過實例的方式,讓你了解Nodejs能夠做什么,可以解決一些什么樣的問題,并且知道它的使用場景。如果你有興趣,請記住一定要自己動手,哪怕照著實例寫一遍,真真實實的感受代碼運行時的喜悅與興奮,激發(fā)自己對新領域的興趣。
默認你已經(jīng)安裝了Nodejs和npm包管理器,并且熟悉一些簡單的操作,如nodejs代碼的運行啟動,npm包的安裝命令等基礎操作。
第一個服務端應用
1.hello world?
首先通過一個前端工程師最常接觸卻不屬于前端范疇的內容去了解一下Nodejs,創(chuàng)建一個http服務。這里使用Nodejs自帶的http模塊創(chuàng)建一個http服務,你可以使用通過瀏覽器或者命令行來發(fā)起一個http請求,直觀的感受服務端的JavaScript。
// http.jsconst http = require('http');http.createServer((req, res) => { res.end('Hello World!');}).listen(8000, ()=> { console.log('listen on 8000!');})上面的例子中,通過使用node自帶的http模塊,調用其http.creatServer方法在本機上開啟了一個http服務,監(jiān)聽了本地的8000端口,代碼邏輯很簡單,當接收到一個req請求時,調用res.end返回一個字符串"hello world"給帶客戶端,旨在讓你對Nodejs有一個直觀的體驗。
可以使用node http.js命令來執(zhí)行這段代碼,通過瀏覽器來訪問http://127.0.0.1:8000或者http://localhost:800來查看結果。
一個由Nodejs的http服務提供的hello world跑起來了,簡潔快速吧。接下來再來實現(xiàn)一個前端工作中與服務端最緊密的內容來看看Nodejs的魅力,數(shù)據(jù)接口。
2. 如何提供一個API?
首先這里確定所要提供的api是我們最常用的json格式,所以我們要注意后端返回給前端的數(shù)據(jù)類型。
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!');})上例子中,先確定了一個數(shù)據(jù)模型data,內部一共有三個字段。這里的數(shù)據(jù)模型就是前端開發(fā)前與后端所定義的返回格式,最終前端要拿到這個JSON格式的數(shù)據(jù)在客戶端進行處理。代碼邏輯相比于Hello World,規(guī)定了返回的數(shù)據(jù)格式,以及設定了返回請求的文本類型為application/json,然后調用res.end返回到客戶端。
可以繼續(xù)使用瀏覽器發(fā)起http請求來查看結果,一個簡單且熟悉的JSON數(shù)據(jù)接口已經(jīng)完成了。你可以按照前端最常用的調用方式,如ajax或者axios來請求接口來在你的前端項目使用它。
但是上面例子中的接口和我們常用的接口有一個差異點,就是接口名稱和返回內容均不規(guī)范,使用者直接通過沒有路徑的http://127.0.0.1:8000來使用接口,這跟我們日常使用的接口是完全不一樣的,那我們接下來再看一下如何給提供一個規(guī)范化的接口呢?
3.一個規(guī)范的接口
規(guī)范的接口具備哪些條件呢?簡單總結一下。
接口名稱:接口名稱要體現(xiàn)出大致的使用場景,例如增刪改查的動作。
接口返回:接口返回要有規(guī)范化的標識,如成功與否錯誤內容等。
接下來通過上面這兩個點,按照標準的接口規(guī)范來實現(xiàn)一下上面的接口,看看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參數(shù) const uid = qs.parse(reqUrl.query).userId; // 生成返回值 const result = JSON.stringify(genResponse(uid)); res.end(result); } else { res.writeHeader(404); res.end('NotFund'); }}).listen(8000, ()=> { console.log('listen on 8000!');})上面的例子中,新使用Nodejs另一個自帶的模塊url,url模塊顧名思義是一個處理href的庫,它將href拆分成各個子內容,同時為了能處理客戶端帶來的userId參數(shù)還使用了自帶的querystring模塊,它可以將鏈接上問號后的query參數(shù)獲取到,以便服務端代碼能使用他們,他們均屬于工具庫,下面看看官方對于URL模塊將href拆分的顆粒度圖,清晰的了解一下一個請求鏈接,可以被拆分成什么顆粒度。
實例中的源碼簡單解析一下,當服務接收到請求時,先判斷請求的api名稱是不是事先約定好的/api/search/data,判斷通過后,將前端傳遞在鏈接上的參數(shù)userId獲取到,處理后插入到返回的json數(shù)據(jù)中,即可通過res.end來下發(fā)數(shù)據(jù),如果路徑判斷失敗,則返回404的狀態(tài)碼,并且進入Notfund頁面,
一個規(guī)范的接口已經(jīng)開發(fā)完成了,簡單總結一下,上面以漸進式的方式了解了Nodejs如何給前端來提供一個規(guī)范化的http接口,了解了服務端的JavaScript所具備的能力,接下來再從另一個前端工程師比較少接觸的內容——文件操作,來進一步了解Nodejs。
文件操作那些事
對于文件操作相關的內容,前端程序員一般是不會觸及的,而且JavaScript語言本身也并沒有暴露操作文件的方法。而在Nodejs中,本身便提供了fs文件操作模塊,這個模塊模塊底層并不是JavaScript來編寫的,是具備操作文件的C++語言編寫的,其封裝完成后將上層暴露給Nodejs,然后便可以使用JavaScript的語法來調用它。
1.讀一個文件
在Nodejs中,讀文件有兩種形式,一種是同步的另一種是異步的,同步可以理解為讀文件這個過程要等待,就是一旦執(zhí)行的讀這個操作的時候,你的代碼就被”卡“住了,直到文件讀完才能繼續(xù)執(zhí)行,來看看下面的例子。
先新增一個test.md文件配合讀操作,文件內容為:### 我是一個文件
// fsread.jsconst fs = require('fs');const file = fs.readFileSync('./test.md', 'utf8');console.log(file);// ### 我是一個文件使用node fsread.js來運行上面的代碼,從上面簡單的幾行你就可以發(fā)現(xiàn)成功將test.md文件里的內容讀出來,可以打印到了命令行console里,突然發(fā)現(xiàn)JavaScript語言的強大了吧,很神奇吧。
但是Nodejs天生是為異步而生的,所以必須要體驗一下異步讀文件是怎么的過程,與同步的表現(xiàn)有何異同。所以?下面示例一個異步回調的方式去讀一個文件,異步的意思就是讀文件這個操作進行的同時,讀操作下面的JavaScript代碼也在執(zhí)行,就如同我們熟悉的軟件后臺運行一樣,你可以繼續(xù)你的桌面操作。
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');在上面的例子中,要求是一次讀取兩個文件,兩個文件之間并沒有相關依賴性,所以這種 場景下我們更希望他們各做各的,無需去等。所以沒有必要像上面同步的方式,等第一個結束再進入第二個的讀取,所以使用異步方式更合適。
從上面的執(zhí)行結果也可以看出來,fs.readFile這個異步回調操作均在三個同步代碼 console的后面,并沒有像同步等待讀操作的結束。
下面來個圖看看這個同步API和異步API有何異同。
圖片上半部分是異步讀文件,可以看出來,讀的操作可以理解為同時刻執(zhí)行的。
圖片下半部分是同步讀文件,第二個讀的操作需要先等待第一個讀完才可以。
舉個現(xiàn)實生活中同步的場景,運動會接力賽,A,B兩個班比賽接力,雖然A,B兩個班無依賴,但是A班的第二名同學則需要第一名同學的接力棒拿到后才可繼續(xù)跑,此時A班的運動員之間就屬于同步阻塞類型。
在舉個異步的場景,老板通過全員會議下達了一個任務,任務是大家做一百個俯臥撐,誰先做完任務則可以領取10000元紅包的獎勵,大家聽到后紛紛原地做起,在這時候各個員工之間就是異步的,他們各做各的,誰先做完就可以執(zhí)行老板給他們的開始說的領取獎勵操作,這個操作可以理解為異步回調函數(shù)。
2. 寫一個文件
Nodejs寫文件也是有兩個類型,同步與異步,實際執(zhí)行流程與上面的“讀”是一樣的。
下面進入同步讀文件的例子,執(zhí)行下面的代碼你會發(fā)現(xiàn)多了一個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提供了豐富的文件操作接口,除了讀寫,還有像復制,給文件授權,刪除一個文件,文件夾的操作,文件內容的監(jiān)聽等,如果你有對文件的操作需求,請先在文檔查一下看是否能夠滿足你。?
文檔地址:http://nodejs.cn/api/fs.html
下面來一個文件內容監(jiān)聽的例子,帶你看看一個文件變化時也能被觀察到樂趣。
const fs = require('fs');fs.watch('./test6.md', 'utf8', (eventType, filename)=>{ // eventType 是 'rename' 或 'change', // filename 是觸發(fā)事件的文件的名稱 console.log('eventType', eventType); console.log('filename', filename);});我將test6.md的內容進行手動的變化,并且改了名字,這里都被監(jiān)聽到了,是不是很有趣,跟我一起來練習吧。
總結
本文從前端工程師們最常接觸卻又不屬于前端領域的兩個方面,http服務與文件操作展開了學習,從幾個簡單易懂的例子帶領去了解了Nodejs。回想當初我為什么學習Nodejs,其實就是因為它的簡單便捷,幾行代碼就能做出一些我想要的效果,能快速的完成我的要求。
如果上面的入門示例也讓你對Nodejs有了濃厚的興趣,那么請快速動手學習起來吧,看再多文章不如自己手寫一遍,從零到一,跟我一起學習吧。
文章用到的代碼均可在此獲取:
https://github.com/FantasyGao/Practice-book/tree/master/nodejs
如上內容均為自己總結,難免會有錯誤或者認識偏差,如有問題,希望大家留言指正,以免誤人,若有什么問題請留言,會盡力回答之。如果對你有幫助不要忘了分享給你的朋友或者點擊右下方的“在看”哦!也可以關注作者,查看歷史文章并且關注最新動態(tài),助你早日成為一名全棧工程師!
總結
以上是生活随笔為你收集整理的2万人同时访问 nodejs_面向前端工程师的Nodejs入门手册(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nginx实现ip端口转发_Nginx实
- 下一篇: 2017年html5行业报告,云适配发布