基於Chrome
的v8
引擎執行js
程式碼,因此我們可以擺脫瀏覽器環境,直接在控制檯中執行js
程式碼,比如下面這個hello world
程式碼
console.log('hello world');
控制檯中直接使用node
即可執行
node.js
的內建模組http
提供了基本的http
服務的能力,基於CommonJS
規範,我們可以使用require
匯入http
模組進行使用http
模組中有一個createServer
函數能夠讓我們建立一個http
伺服器
其接收一個回撥函數作為引數,這個回撥函數接收兩個引數 -- request
和response
request
包括所有使用者端請求的資訊,比如url
、請求頭header
、請求方式和請求體等response
主要用於返回資訊給使用者端,封裝了一些操作響應體相關的操作,比如response.writeHead
方法就可以讓我們自定義返回體的頭部資訊和狀態碼當我們將響應體處理好了之後,呼叫response.end()
方法就可以將響應體傳送給使用者端
使用createServer
函數只是幫我們建立了一個Server
物件,並沒有讓其開啟監聽,我們還需要呼叫server
物件的listen
方法才可以進行監聽,真正作為一個伺服器開始執行
listen
方法的第一個引數是監聽的埠號,第二個引數則是繫結的主機ip
,第三個引數是一個回撥函數,會被http
模組非同步呼叫,當遇到錯誤的時候,就能夠在這個回撥函數的第一個引數中獲取到丟擲的異常 ,我們可以選擇對異常進行處理,讓我們的伺服器更加健壯下面是使用http
模組建立一個簡單伺服器的例子
const { createServer } = require('http'); const HOST = 'localhost'; const PORT = '8080'; const server = createServer((req, resp) => { // the first param is status code it returns // and the second param is response header info resp.writeHead(200, { 'Content-Type': 'text/plain' }); console.log('server is working...'); // call end method to tell server that the request has been fulfilled resp.end('hello nodejs http server'); }); server.listen(PORT, HOST, (error) => { if (error) { console.log('Something wrong: ', error); return; } console.log(`server is listening on http://${HOST}:${PORT} ...`); });
可以直接嘗試用node
執行它,創造一個屬於你的伺服器!伺服器執行後,瀏覽器存取http://localhost:8080即可存取到這個伺服器
也可以使用nodemon
執行它,這樣當我們的程式碼發生變化的時候就不需要手動終止程式再重新執行了
npm i -g nodemon
建議全域性安裝它,這樣就可以直接使用,不需要通過npx nodemon
去使用
使用也很簡單,直接將node
命令改成nodemon
命令即可
nodemon http-server.js
前面我們在使用createServer
以及resp
物件的時候,看不到任何的語法提示,必須隨時跟著node
官方檔案去邊用邊查,有點不方便
但是沒關係,我們可以使用ts
的.d.ts
檔案幫助我們提供語法提示功能,注意,我們不是使用ts
進行開發,只是使用它的語法提示功能而已
npm init -y
@types/node
-- pnpm i @types/node -D
jsconfig.json
檔案,將node_modules
排除在外,沒必要對其進行檢查{ "compilerOptions": { "checkJs": true }, "exclude": ["node_modules", "**/node_modules/*"] }
不知道你是否有發現上面的程式碼其實是有一處錯誤的呢?checkJs
能夠幫助我們檢查型別錯誤問題,可以根據需要選擇是否開啟
可以看到,開啟檢查後立馬就給我們提示了引數型別不匹配的問題
這時候將滑鼠懸浮在listen
方法上,就能夠看到該方法的簽名
可以看到,原來port
引數需要是number
型別,但是我們定義的時候是string
型別,所以沒匹配上,將其修改為number
的8080
即可
而且可以直接檢視到相關api
的檔案,不需要開啟node
官方的檔案找半天去檢視了
前面我們的簡單http server
中只返回了一句話,那麼是否能夠返回多句話呢?
這就要用到resp
物件的write
方法了,end
只能夠返回一次內容,而是用write
方法,我們可以多次寫入內容到響應體中,最後只用呼叫一次end
,並且不傳遞任何引數,只讓他完成傳送響應體的功能
const { createServer } = require("http"); const HOST = "localhost"; const PORT = 8080; const server = createServer((req, resp) => { resp.writeHead(200, { "Content-Type": "text/plain" }); console.log("server is working..."); // write some lorem sentences resp.write("Lorem ipsum dolor sit amet consectetur adipisicing elit.\n"); resp.write("Omnis eligendi aperiam delectus?\n"); resp.write("Aut, quam quo!\n"); resp.end(); }); server.listen(PORT, HOST, (error) => { if (error) { console.log("Something wrong: ", error); return; } console.log(`server is listening on http://${HOST}:${PORT} ...`); });
這次我們寫入了三句話,現在的效果就變成這樣啦
我們不僅可以返回字串給瀏覽器,還可以直接讀取html
檔案的內容並將其作為結果返回給瀏覽器
這就需要用到另一個Node.js
的內建模組 -- fs
,該模組提供了檔案操作的功能
使用fs.readFile
可以非同步進行讀取檔案的操作,但是它不會返回promise
物件,因此我們需要傳入回撥去處理讀取到檔案後的操作
還可以使用fs.readFileSync
進行同步阻塞讀取檔案,這裡我們選擇非同步讀取
const { createServer } = require("http"); const fs = require("fs"); const HOST = "localhost"; const PORT = 8080;const server = createServer((req, resp) => { // change the MIME type from text/plain to text/html resp.writeHead(200, { "Content-Type": "text/html" }); // read the html file content fs.readFile("index.html", (err, data) => { if (err) { console.error( "an error occurred while reading the html file content: ", err ); throw err; } console.log("operation success!"); resp.write(data); resp.end(); }); }); server.listen(PORT, HOST, (error) => { if (error) { console.log("Something wrong: ", error); return; } console.log(`server is listening on http://${HOST}:${PORT} ...`); });
現在的結果就像下面這樣:
成功將html
返回注意:這裡需要將響應頭的**Content-Type**
改為**text/html**
,告知瀏覽器我們返回的是**html**
檔案的內容,如果仍然以**text/plain**
返回的話,瀏覽器不會對返回的內容進行解析,即便它是符合**html**
語法的也不會解析,就像下面這樣:
當我們需要編寫一個後端伺服器,只負責返回介面資料的時候,就需要返回json
格式的內容了,相信聰明的你也知道該怎麼處理了:
MIME
型別設定為application/json
resp.write
的時候傳入的是json
字串,可以使用JSON.stringify
處理物件後返回const { createServer } = require("http"); const HOST = "localhost"; const PORT = 8080; const server = createServer((req, resp) => { // change the MIME type to application/json resp.writeHead(200, { "Content-Type": "application/json" }); // create a json data by using an object const jsonDataObj = { code: 0, message: "success", data: { name: "plasticine", age: 20, hobby: "coding", }, }; resp.write(JSON.stringify(jsonDataObj)); resp.end(); }); server.listen(PORT, HOST, (error) => { if (error) { console.log("Something wrong: ", error); return; } console.log(`server is listening on http://${HOST}:${PORT} ...`); });
結果如下:
和之前返回html
檔案的思路類似,都是一個設定響應頭MIME
型別,讀取檔案,返回檔案內容的過程
但是這次我們搞點不一樣的
我們的思路是在伺服器執行的時候生成一個pdf
檔案,並將它返回
還需要將MIME
的型別改為application/pdf
生成pdf
檔案需要用到一個庫 -- pdfkit
pnpm i pdfkit
首先我們編寫一個建立pdf
檔案的函數,因為建立pdf
檔案還需要進行一些寫入操作,不確定什麼時候會完成,但是我們的請求必須等到pdf
檔案建立完成後才能得到響應
所以我們需要將它變成非同步進行的,返回一個promise
/** * @description 建立 pdf 檔案 */const createPdf = () => { return new Promise((resolve, reject) => { if (!fs.existsSync("example.pdf")) { // create a PDFDocument object const doc = new PDFDocument(); // create write stream by piping the pdf content. doc.pipe(fs.createWriteStream("example.pdf")); // add some contents to pdf document doc.fontSize(16).text("Hello PDF", 100, 100); // complete the operation of generating PDF file. doc.end(); } resolve("success"); }); };
這裡使用到了管道操作,將PDFDocument
物件的內容通過管道傳到新建立的寫入流中,當完成操作後我們就通過resovle
告知外界已經建立好pdf
檔案了
然後在伺服器端程式碼中呼叫
const server = createServer(async (req, resp) => { // change the MIME type to application/pdf resp.writeHead(200, { "Content-Type": "application/pdf" }); // create pdf file await createPdf(); // read created pdf file fs.readFile("example.pdf", (err, data) => { if (err) { console.error( "an error occurred while reading the pdf file content: ", err ); throw err; } console.log("operation success!"); resp.end(data); }); }); server.listen(PORT, HOST, (error) => { if (error) { console.log("Something wrong: ", error); return; } console.log(`server is listening on http://${HOST}:${PORT} ...`); });
現在瀏覽器就可以讀取到建立的pdf
檔案了
思路依然是一樣的,讀取一個音訊檔,然後通過管道將它送到resp
物件中再返回即可
const { createServer } = require("http"); const { stat, createReadStream } = require("fs"); const HOST = "localhost"; const PORT = 8080; const server = createServer((req, resp) => { // change the MIME type to audio/mpe resp.writeHead(200, { "Content-Type": "audio/mp3" }); const mp3FileName = "audio.mp3"; stat(mp3FileName, (err, stats) => { if (stats.isFile()) { const rs = createReadStream(mp3FileName); // pipe the read stream to resp rs.pipe(resp); } else { resp.end("mp3 file not exists"); } }); }); server.listen(PORT, HOST, (error) => { if (error) { console.log("Something wrong: ", error); return; } console.log(`server is listening on http://${HOST}:${PORT} ...`); });
效果如下
開啟後就是一個播放音訊的介面,這是chrome
提供的對音訊檔的展示,並且開啟控制檯會發現有返回音訊檔
注意:將音訊檔流通過管道傳到**resp**
後,不需要呼叫**resp.end()**
方法,因為這會關閉整個響應,導致音訊檔無法獲取
視訊檔和音訊檔的處理是一樣的,只是MIME
的型別要改成video/mp4
,其他都一樣
const { createServer } = require("http"); const { stat, createReadStream } = require("fs"); const HOST = "localhost"; const PORT = 8080; const server = createServer((req, resp) => { // change the MIME type to audio/mpe resp.writeHead(200, { "Content-Type": "audio/mp4" }); const mp4FileName = "video.mp4"; stat(mp4FileName, (err, stats) => { if (stats.isFile()) { const rs = createReadStream(mp4FileName); // pipe the read stream to resp rs.pipe(resp); } else { resp.end("mp4 file not exists"); } }); }); server.listen(PORT, HOST, (error) => { if (error) { console.log("Something wrong: ", error); return; } console.log(`server is listening on http://${HOST}:${PORT} ...`); });
我們學會了:
Node
建立一個http
伺服器js
加上型別提示html
JSON
pdf
檔案雖然內容簡單,但還是希望你能跟著動手敲一敲,不要以為簡單就看看就算了,看了不代表會了,真正動手實現過後才會找到自己的問題
更多node相關知識,請存取:!
以上就是聊聊怎麼使用Node.js建立一個簡單的HTTP伺服器的詳細內容,更多請關注TW511.COM其它相關文章!