### 明天要去面試了 今天晚上突擊一下node.js
-
什么是Node.js?它有什么特點?
Node.js是一個基于Chrome V8引擎的JavaScript運行環境,它允許在服務器端運行JavaScript代碼。它的特點包括單線程、非阻塞I/O、事件驅動等? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??單線程:想象你一個人在餐廳工作。你既是服務員,又是廚師。你一次只能做一件事,比如你正在給客人上菜,這時候你就不能同時做其他事情,比如炒菜。但是,一旦你上完菜,你就可以去做下一件事,比如準備另一道菜。在Node.js中,也是這樣的,它就像一個單線程的餐廳,一次只能做一件事,但它可以快速地在不同的事情之間切換。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?非阻塞I/O還是在餐廳的例子中,你是一個很有效率的服務員。當你在給客人上菜的時候,你不需要站在桌邊等他們吃完,而是可以立刻去服務其他客人或者做其他事情。在計算機術語中,這就像是你在請求數據或者進行其他操作時,不需要等待結果,你可以繼續做其他事情。當數據準備好了,它會告訴你,然后你再去處理它。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?事件驅動:想象你的餐廳有一個任務清單,上面列出了所有需要做的事情,比如上菜、結賬、打掃衛生等。每當你完成一個任務,你就在清單上劃掉它,然后去做下一個任務。在Node.js中,也是這樣的,它有一個“事件清單”,每當有事情發生(比如一個文件讀取完成,或者一個網絡請求到來),Node.js就會去處理這個事件,處理完后就去做下一件事。 - 解釋Node.js中的非阻塞I/O和事件驅動模型。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?非阻塞I/O意味著在執行I/O操作(如讀寫文件、數據庫操作等)時,Node.js不會等待操作完成,而是繼續執行其他任務。事件驅動模型是基于事件和回調函數的,Node.js中的許多API都是基于這種模型設計的。
- 什么是回調地獄,如何避免它? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 回調地獄是指由于過多嵌套的回調函數導致的代碼難以閱讀和維護的問題。為了避免回調地獄,可以使用Promise、async/await等語法來編寫更扁平化的代碼。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 首先,讓我們想象一下,你有一個任務列表,每個任務完成后才能開始下一個任務。在編程中,這些任務可能是異步操作,比如從服務器獲取數據、讀取文件、或者等待用戶輸入。
回調地獄是這樣的:
你開始做第一個任務,并且告訴你的助手,當第一個任務完成時,請通知你,然后開始第二個任務。
當第一個任務完成時,你的助手告訴你,你開始做第二個任務,并告訴助手,當第二個任務完成時,請通知你,然后開始第三個任務。
這個過程一直持續下去,每次都要等待前一個任務完成,然后才能開始下一個任務。
在代碼中,這就形成了很多層嵌套的回調函數,每個回調函數都在等待前一個異步操作完成。這樣的代碼看起來像這樣:task1(function() {task2(function() {task3(function() {// ...更多的任務});}); });
這種代碼結構很難閱讀,如果你有很多這樣的任務,代碼會變得越來越亂,這就是所謂的“回調地獄”。 為了避免回調地獄,我們可以使用Promise: Promise就像是一個代表未來某個時刻可能完成的任務的占位符。你可以告訴Promise,當任務完成時應該做什么。 使用Promise,上面的代碼看起來會像這樣:
task1().then(task2).then(task3).then(() => {// ...更多的任務});
async/await: async/await是JavaScript中的一種語法,它讓我們可以用更接近同步代碼的方式來寫異步代碼。 使用async/await,上面的代碼看起來會像這樣:
async function doTasks() {await task1();await task2();await task3();// ...更多的任務 }
-
解釋Node.js中的事件循環。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??事件循環是Node.js的核心概念,它負責調度和執行所有進入事件隊列的回調函數。它允許Node.js執行非阻塞I/O操作,并在操作完成后通過回調函數處理結果。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?想象你是一名忙碌的餐廳服務員,你有很多事情要做,比如給客人上菜、結賬、打掃衛生等。你不可能同時做所有的事情,所以你需要一個方法來決定先做哪件事,后做哪件事。 在Node.js中,事件循環就像是你的大腦,它幫助你決定下一步該做什么。你有一個小本子(事件隊列),上面列出了所有你需要做的事情。你一次只能做一件事,但你可以快速地在不同的事情之間切換。 你上菜給客人(執行一個任務)。 你做完這件事后,就在小本子上劃掉它(從事件隊列中移除這個事件)。 然后你檢查小本子,看看接下來該做什么(事件循環檢查事件隊列中的下一個事件)。 你去做下一件事(執行下一個任務)。 這個過程一直重復,你總是在做下一件最重要的事情,而且你總是在小本子上劃掉已經完成的事情。 在Node.js中,這也是類似的: Node.js開始執行一些代碼(比如從服務器請求數據)。 如果這是一個異步操作(比如讀取文件或者等待網絡響應),Node.js不會等待它完成,而是繼續做其他事情。 當異步操作完成時,它會告訴事件循環:“嘿,我完成了,你可以處理結果了”。 事件循環會在事件隊列中添加一個事件,表示這個異步操作已經完成。 Node.js完成當前的任務后,事件循環會檢查事件隊列,看看是否有新的任務需要處理(比如處理異步操作的結果)。 如果有,Node.js就會處理這個事件,執行相應的回調函數。 這樣,Node.js可以同時處理很多件事情,因為它不需要等待任何事情完成,而是在事情完成時處理它們。這就是事件循環如何在Node.js中工作的。
-
如何在Node.js中創建一個HTTP服務器?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??使用Node.js內置的
http
模塊可以輕松創建一個HTTP服務器。例如//這行代碼引入了Node.js內置的http模塊,這個模塊提供了創建HTTP服務器和客戶端的功能。 const http = require('http'); //這行代碼創建了一個新的HTTP服務器。createServer函數接受一個回調函數作為參數,這個回調函數會在每 //次有請求到達服務器時被調用。這個回調函數有兩個參數:req(請求對象)和res(響應對象)。 const server = http.createServer((req, res) => { //這行代碼告訴服務器,當有請求來的時候,返回一個HTTP狀態碼200,表示請求成功。同時設置響應頭 //Content-Type為text/plain,這意味著返回的內容是純文本。res.writeHead(200, {'Content-Type': 'text/plain'}); //這行代碼結束了響應,并且發送了內容Hello, World!給客戶端。每次服務器接收到請求時,都會發送這個 //消息。res.end('Hello, World!\n'); }); //這行代碼讓服務器開始監聽3000端口的請求。當服務器啟動并且開始監聽時,它會執行回調函數,打印出Server running at http://localhost:3000/這個消息。 server.listen(3000, () => {console.log('Server running at http://localhost:3000/'); });
-
什么是Express框架?它有什么作用?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??Express是一個輕量級的Node.js框架,它提供了一組強大的功能,如路由、中間件等,使得構建Web應用程序更加快速和簡單。在Node.js和Express框架中,中間件是一種特殊類型的函數,它在請求和響應周期中被調用,可以用來處理請求和響應對象。
-
什么是NPM?如何使用它??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NPM(Node Package Manager)是Node.js的包管理器,它允許你安裝、管理和共享Node.js模塊。使用NPM,你可以通過命令行工具來安裝包,如
npm install <package-name>
。 -
解釋模塊化編程在Node.js中的作用。??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Node.js采用CommonJS模塊化規范,允許開發者將代碼分割成多個文件(模塊),并通過
require
函數導入其他模塊。這種模塊化編程方式有助于代碼的組織和維護。 -
如何在Node.js中讀取和寫入文件?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??使用Node.js內置的
fs
模塊可以讀取和寫入文件fs.writeFile('example.txt', 'Hello, World!', err => {if (err) throw err;console.log('The file has been saved!'); }); const fs = require('fs'); fs.readFile('example.txt', 'utf8', (err, data) => {if (err) throw err;console.log(data); });
-
如何在Node.js中處理異步錯誤?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?在Node.js中,異步錯誤通常通過回調函數的第一個參數傳遞。例如
fs.readFile('example.txt', 'utf8', (err, data) => {if (err) {console.error('Error reading file:', err);return;}console.log(data); });
使用Promise時,可以使用
.catch()
方法捕獲錯誤:fs.promises.readFile('example.txt', 'utf8').then(data => console.log(data)).catch(err => console.error('Error reading file:', err));