2017 版 Node.js 面試問題及答案

lilji410 7年前發布 | 10K 次閱讀 Node.js Node.js 開發

兩年前,我們發布了我們的第一篇關于Node.js面試的文章 Node.js面試常見問題和答案 ,近兩年,JavaScript和Node.js生態系統有了很多更新和發展,因此,是該更新這些面試問題和答案的時候了。

免責聲明(重要)

僅僅通過面試問題去評價一個面試者,從來都不是一個好的選擇。但是 這些問題可以讓你大體了解面試者在Node.js開發上的經驗。

當然,這些問題并不能全面反映一個人的思維方式和開發習慣。

我相信,開發中遇到的問題,更能反映面試者的知識水平 - 所以,我們鼓勵面試者和候選者做結對編程(結對編程技術是指兩位程序員坐在同一工作臺前開發軟件)。

最后也是最重要的:我們都是人,要盡最大的可能讓面試者感到尊重和被歡迎。這些問題并不意味著題目和正確答案,只是讓面試有話可聊。

2017 Node.js面試問題

  • 什么是error-first回調模式?

  • 如何避免“回調地獄”?

  • 什么是Promises?

  • 什么工具統一團隊的代碼風格?為什么統一的代碼風格很重要?

  • 什么時候應當用npm?什么時候應當用yarn?

  • 什么是樁代碼(stub)? 請描述一個應用場景!

  • 什么是測試金字塔?請舉例說明!

  • 你最欣賞的HTTP框架是什么?為什么?

  • 如果保證你的cookie安全?如何阻止XSS攻擊?

  • 如何確認項目的相關依賴安全?

答案

什么是error-first回調模式?

應用error-first回調模式是為了更好的進行錯誤和數據的傳遞。第一個參數保留給一個錯誤error對象,一旦出錯,錯誤將通過第一個參數error返回。其余的參數將用作數據的傳遞。

fs.readFile(filePath, function(err, data) {  
  if (err) {
    // handle the error, the return is important here
    // so execution stops here
    return console.log(err)
  }
  // use the data object
  console.log(data)
})

如何避免“回調地獄”?

解決這個問題的方法有很多:

  • 模塊化設計: 講回調拆分成幾個獨立的函數

  • 使用 流程控制庫 , 比如 async

  • 組合使用 generators和Promises

  • 使用 async/await 函數 (只能在Node v7 release版本運行, Node LTS版本尚不支持

什么是Promises?

promise的概念早在上個世紀八十年代就被提出,現在已經是大多數現代編程語言中支持的特性,讓你能更輕松地實現異步模型。

舉個簡單的例子, 正常來說100ms 之后將會輸出 result 。一旦失敗, catch 可以拋出異常。Promises允許鏈式操作。

new Promise((resolve, reject) => {  
  setTimeout(() => {
    resolve('result')
  }, 100)
})
  .then(console.log)
  .catch(console.error)

什么工具統一團隊的代碼風格? 為什么統一的代碼風格很重要?

團隊協作時,始終如一的代碼風格十分重要,代碼風格一致,團隊成員可以更輕松的構建項目,不用為每次構建項目都使用新的代碼風格而擔心。

同時, 始終如一的代碼風格,可以通過靜態分析排除代碼問題。

幫助規范代碼的工具:

如果你想更上一層樓,我推薦你立刻學習 JavaScript Clean Coding 原則。

什么是樁代碼(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()

什么是測試金字塔?請舉例說明!

測試金字塔描述了單元測試(unit test),集成測試(integration tests),端到端測試(end-to-end test)在測試中占的比例。

舉個例子,測試一個HTTP API需要:

  • 大量關于models 的單元測試 ( 使用樁代碼處理 ) ,

  • 一些關于models如何和其他models交互的集成測試 ( 未使用樁代碼處理 ) ,

  • 少量的端到端測試,也就是真實環境下的調用 ( 未使用樁代碼處理 ) .

你最欣賞的HTTP框架是什么?為什么?

這道題沒有標準答案。出這道題的目的是,看看面試者對他所使用框架,理解的有多深。只要面試者回答出框架的優缺點,為什么使用這個框架就可以了。

什么時候應該在后臺進程中使用消息服務?怎么處理工作線程的任務/怎么給worker安排任務?

消息隊列適用于后臺數據傳輸服務,比如發送郵件和數據圖像處理。

消息隊列有很多解決方案,比如 RabbitMQ 和 Kafka .

如何保證你的cookie安全?如何阻止XSS攻擊?

XSS攻擊是指攻擊者向Html頁面里插入惡意JavaScript代碼。

為了防止攻擊,你需要對HTTP header里的 set-cookie 進行處理:

  • HttpOnly- 這個屬性幫助防止跨站腳本攻擊,它禁止通過JavaScript訪問cookie。

  • secure- 這個屬性告訴瀏覽器,僅允許通過HTTPS協議訪問cookie。

所以,你需要做的是在請求頭里寫 Set-Cookie: sid=; HttpOnly 。如果你正在使用Express框架,可以使用 express-cookie session ,他會默認做出上述防止XSS攻擊的設置。

如何確認項目的相關依賴安全?

使用Node.js開發, 很容易出現有成百上千個依賴的情況

舉例來說,如果你依賴Express,準確的說這意味著也依賴 27 個其他的模塊 , 手動檢測更新這些模塊不是一個的選擇!

唯一的選擇就是自動的安全的更新你的依賴,你有如下免費或付費的選擇:

Node.js 答疑解惑

下面這部分主要給正在準備Node.js 面試者解決一些困惑和棘手的問題。

下面的代碼有什么錯誤?

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)

如果你調試一個巨大的代碼庫,并且比不知道哪個Promise函數有潛在的問題, 你可以使用 unhandledRejection 這個工具。它將會打印出所有未處理的reject狀態的Promise。

process.on('unhandledRejection', (err) => {  
  console.log(err)
})

下面的代碼有什么錯誤?

function checkApiKey (apiKeyFromDb, apiKeyReceived) {  
  if (apiKeyFromDb === apiKeyReceived) {
    return true
  }
  return false
}

答案

在進行數據校驗(security credentials)時,避免任何信息泄露是最重要的。所以,我們要控制數據校驗的執行時間。我們要保證,不管傳過來的數據是什么,我們校驗數據消耗的時間是相同的。如果你做不到這一點,你的程序對 時序攻擊 的抵抗力很低。

為什么會有這種現象?

Node.js使用的V8 JavaScript引擎會從性能角度優化你的代碼。V8引擎比較數據的方式是字節比較, 一旦發現有一個字節不一致, 比較運算就會停止。 因此,攻擊者傳入的password校驗時間越長,說明password正確的部分越多。

為了修復這個問題, 你可以使用npm模塊 cryptiles 。

function checkApiKey (apiKeyFromDb, apiKeyReceived) {  
  return cryptiles.fixedTimeComparison(apiKeyFromDb, apiKeyReceived)
}

下面這段代碼輸出的是什么?

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對象,輸出 1

  2. 結果 +1,現在的輸出為 2

  3. 輸出結果被拋棄,拋出一個error

  4. error被丟棄, 返回一個新的value ( 1 )

  5. catch進行異常處理,但catch后程序不停止執行, 返回一個信息+1之后的 value ( 2 )

  6. value正常輸出

  7. value已正常輸出,這一行不會執行

花時間相處一天比技術提問更有效

花至少半天的時間和面試者相處,比考1000道這樣的面試題更有價值

如果你真的這樣做了, 你可以更深入的了解面試者能否適應公司的文化,是否具備契合崗位的技能。

 

來自:http://www.w3ctech.com/topic/1969

 

 本文由用戶 lilji410 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!