譯者按: 從ECMAScript標準,Node.js語法以及NPM模塊角度來看,Node.js的發展讓人應接不暇,那麼面試題也得與時俱進。javascript
原文: Node.js Interview Questions and Answers (2017 Edition)html
譯者: Fundebugjava
問題node
- 什麼是錯誤優先的回調函數?
- 如何避免回調地獄?
- 什麼是Promise?
- 用什麼工具保證一致的代碼風格?爲何要這樣?
- 什麼是Stub?舉例說明
- 什麼是測試金字塔?舉例說明
- 最喜歡哪一個HTTP框架?爲何?
- Cookies如何防範XSS攻擊?
- 如何保證依賴的安全性?git
答案github
1. 什麼是錯誤優先的回調函數?面試
錯誤優先的回調函數(Error-First Callback)用於同時返回錯誤和數據。第一個參數返回錯誤,而且驗證它是否出錯;其餘參數用於返回數據。express
fs.readFile(filePath, function(err, data) { if (err) { // 處理錯誤 return console.log(err); } console.log(data); });
2. 如何避免回調地獄?npm
如下方式能夠避免回調地獄:json
- 模塊化: 將回調函數轉換爲獨立的函數
- 使用流程控制庫,例如[aync](https://www.npmjs.com/package/async)
- 使用Promise
- 使用aync/await(參考[Async/Await替代Promise的6個理由](https://blog.fundebug.com/2017/04/04/nodejs-async-await/))
3. 什麼是Promise?
Promise能夠幫助咱們更好地處理異步操做。下面的示例中,100ms後會打印result字符串。catch用於錯誤處理。多個Promise能夠連接起來。
new Promise((resolve, reject) => { setTimeout(() => { resolve('result'); }, 100) }) .then(console.log) .catch(console.error);
4. 用什麼工具保證一致的代碼風格?爲何要這樣?
團隊協做時,保證一致的代碼風格是很是重要的,這樣團隊成員才能夠更快地修改代碼,而不須要每次去適應新的風格。這些工具能夠幫助咱們:
- [ESLint](http://eslint.org/)
- [Standard](https://standardjs.com/)
感興趣的話,能夠參考JavaScript Clean Coding
5. 什麼是Stub?舉例說明
Stub用於模擬模塊的行爲。測試時,Stub能夠爲函數調用返回模擬的結果。好比說,當咱們寫文件時,實際上並不須要真正去寫。
var fs = require('fs'); var writeFileStub = sinon.stub(fs, 'writeFile', function(path, data, cb) { return cb(null); }); expect(writeFileStub).to.be.called; writeFileStub.restore();
6. 什麼是測試金字塔?舉例說明
測試金字塔反映了須要寫的單元測試、集成測試以及端到端測試的比例:
測試HTTP接口時應該是這樣的:
- 不少單元測試,分別測試各個模塊(依賴須要stub)
- 較少的集成測試,測試各個模塊之間的交互(依賴不能stub)
- 少許端到端測試,去調用真正地接口(依賴不能stub)
7. 最喜歡哪一個HTTP框架?爲何?
這個問題標準答案。須要描述框架的優缺點,這樣能夠反映開發者對框架的熟悉程度。
8. Cookies如何防範XSS攻擊?
XSS(Cross-Site Scripting,跨站腳本攻擊)是指攻擊者在返回的HTML中插入JavaScript腳本。爲了減輕這些攻擊,須要在HTTP頭部配置set-cookie:
- HttpOnly - 這個屬性能夠防止cross-site scripting,由於它會禁止Javascript腳本訪問cookie。
- secure - 這個屬性告訴瀏覽器僅在請求爲HTTPS時發送cookie。
結果應該是這樣的: Set-Cookie: sid=<cookie-value>; HttpOnly. 使用Express的話,cookie-session默認配置好了。
9. 如何保證依賴的安全性?
編寫Node.js應用時,極可能依賴成百上千的模塊。例如,使用了Express的話,會直接依賴27個模塊。所以,手動檢查全部依賴是不現實的。惟一的辦法是對依賴進行自動化的安全檢查,有這些工具可供選擇:
- npm outdated
- [Trace by RisingStack](https://trace.risingstack.com/)
- [NSP](https://nodesecurity.io/)
- [GreenKeeper](https://greenkeeper.io/)
- [Snyk](https://snyk.io/)
附加題
1. 這段代碼有什麼問題?
new Promise((resolve, reject) => { throw new Error('error') }) .then(console.log)
then以後沒有catch。這樣的話,錯誤會被忽略。能夠這樣解決問題:
new Promise((resolve, reject) => { throw new Error('error') }) .then(console.log).catch(console.error)
調試一個大型的項目時,可使用監控unhandledRejection事件來捕獲全部未處理的Promise錯誤:
process.on('unhandledRejection', (err) => { console.log(err) })
------
2. 這段代碼有什麼問題?
function checkApiKey(apiKeyFromDb, apiKeyReceived) { if (apiKeyFromDb === apiKeyReceived) { return true } return false }
比較密碼時,不能泄露任何信息,所以比較必須在固定時間完成。不然,可使用timing attacks來攻擊你的應用。爲何會這樣呢?Node.js使用V8引擎,它會從性能角度優化代碼。它會逐個比較字符串的字母,一旦發現不匹配時就中止比較。當攻擊者的密碼更準確時,比較的時間越長。所以,攻擊者能夠經過比較的時間長短來判斷密碼的正確性。使用[cryptiles](https://www.npmjs.com/package/cryptiles)能夠解決這個問題:
function checkApiKey(apiKeyFromDb, apiKeyReceived) { return cryptiles.fixedTimeComparison(apiKeyFromDb, apiKeyReceived) }
3. 這段代碼的輸出是什麼?
Promise.resolve(1) .then((x) => x + 1) .then((x) => { throw new Error('My Error') }) .catch(() => 1) .then((x) => x + 1) .then((x) => console.log(x)) .catch(console.error)
答案是2,逐行解釋以下:
1. 建立新的Promise,resolve值爲1。
2. x爲1,加1以後返回2。
3. x爲2,可是沒有用到。拋出一個錯誤。
4. 捕獲錯誤,可是沒有處理。返回1。
5. x爲1,加1以後返回2。
6. x爲2,打印2。
7. 不會執行,由於沒有錯誤拋出。
Fundebug專一於JavaScript、微信小程序、微信小遊戲、支付寶小程序、React Native、Node.js和Java實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了7億+錯誤事件,獲得了Google、360、金山軟件、百姓網等衆多知名用戶的承認。歡迎免費試用!
- 10個常見的Node.js面試題
- XSS - Stealing Cookies 101
轉載時請註明做者Fundebug
以及本文地址:https://blog.fundebug.com/2017/04/10/nodejs-interview-2017/