
node.js基於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 有 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 -Djsconfig.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/jsonresp.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加上類型提示htmlJSONpdf文件雖然內容簡單,但還是希望你能跟著動手敲一敲,不要以為簡單就看看就算了,看了不代表會了,真正動手實現過後才會找到自己的問題