錯誤優先的回調函數用於傳遞錯誤和數據。第一個參數始終應該是一個錯誤對象, 用於檢查程序是否發生了錯誤。其他的參數用於傳遞數據。html
s.readFile(filePath, function(err, data) { if (err) { //handle the error } // use the data object
});
解析:這個題目的主要做用在於檢查被面試者對於Node中異步操做的一些基本知識的掌握。node
爲了解決這個阻塞問題,JavaScript嚴重依賴於回調,這是在長時間運行的進程(IO,定時器等)完成後運行的函數,所以容許代碼執行通過長時間運行的任務。nginx
downloadFile('example.com/weather.json', function(err, data) { console.log('Got weather data:', data);
});
可是,問題來了,回調地獄git
雖然回調的概念在理論上是巨大的,但它可能致使一些真正使人困惑和難以閱讀的代碼。 想象一下,若是你須要在回調後進行回調程序員
這種層層嵌套的代碼給開發帶來了不少問題,主要體如今: 1.代碼可能性變差 2.調試困難 3.出現異常後難以排查
在幾乎每種編程語言中,下降複雜性的最好方法之一是模塊化。 JavaScript也不例外。 每當你編寫代碼時,花一些時間來回顧一下你是否常常遇到一個常見的模式。github
你在不一樣的地方屢次寫相同的代碼嗎? 你的代碼的不一樣部分是否遵循一個共同的主題? 若是是這樣,你有機會清理東西,抽象和重用代碼。面試
有數千個模塊,你能夠看看供參考,但這裏有幾個要考慮。 它們處理常見的,但很是具體的任務,不然會擾亂你的代碼並下降可讀性:Pluralize,csv,qs,clone。npm
Here is a new file called formuploader.js that contains our two functions from before:編程
module.exports.submit = formSubmit function formSubmit (submitEvent) { var name = document.querySelector('input').value request({ uri: "http://example.com/upload", body: name, method: "POST" }, postResponse) } function postResponse (err, response, body) { var statusMessage = document.querySelector('.status') if (err) return statusMessage.value = err statusMessage.value = body }
Now that we have formuploader.js (and it is loaded in the page as a script tag after being browserified) we just need to require it and use it! Here is how our application specific code looks now:json
var formUploader = require('formuploader') document.querySelector('form').onsubmit = formUploader.submit
雖然Promises能夠花費一些時間來掌握,但在我看來,它們是您能夠在JavaScript中學習的更重要的概念之一。 它不只大大減小了代碼行數,並且使代碼的邏輯流程更容易遵循。
這裏是一個使用很是快,很是受歡迎的Promise庫,Bluebird的例子
var Promise = require('bluebird'); var fs = require('fs'); Promise.promisifyAll(fs); var myFile = '/tmp/test'; fs.readFileAsync(myFile, 'utf8').then(function(txt) { txt = txt + '\nAppended something!'; fs.writeFile(myFile, txt); }).then(function() { console.log('Appended text!'); }).catch(function(err) { console.log(err); });
請注意,這個解決方案不只比之前的解決方案更短,並且更容易閱讀(儘管,誠然,Promise風格的代碼可能須要一些習慣)。 花時間學習和理解承諾,這將是值得你的時間。 可是,Promise絕對不是解決咱們在異步編程中的全部問題,因此不要假設經過使用它們,你會有一個快速,乾淨,無bug的應用程序。 關鍵是知道何時對你有用。
一些Promise庫你應該檢查是Q,bluebird,或內置Promises若是你使用ES6的話。
注意:這是一個ES7功能,目前不支持Node或io.js。 可是,你如今可使用它像Babel同樣的轉換器。
清除代碼的另外一個選項是我最近喜歡的(當它有更普遍的支持時),它使用異步函數。 這將容許你編寫看起來更像同步代碼,但仍然是異步的代碼。
async function getUser(id) { if (id) { return await db.user.byId(id); } else { throw 'Invalid ID!'; } } try { let user = await getUser(123); } catch(err) { console.error(err); }
The db.user.byId(id) call returns a Promise , which we'd normally have to use with .then() , but with await we can return the resolved value directly. Notice that the function containing the await call is prefixed with async , which tells us that it contains asynchronous code and must also be called with await. Another big advantage to this method is we can now use try/catch, for, and while with our asynchronous functions,which is much more intuitive than chaining promises together.Aside from using transpilers like Babel and Traceur, you can also get functionality like this in Node with the asyncawait package.
async/await 語法到底好在哪裏?一圖勝千言
這題有陷阱!在類Unix系統中你不該該嘗試去監聽80端口,由於這須要超級用戶權限。 所以不推薦讓你的應用直接監聽這個端口。
目前,若是你必定要讓你的應用監聽80端口的話,你能夠有經過在Node應用的前方再增長一層反向代理 (例如nginx)來實現,以下圖所示。不然,建議你直接監聽大於1024的端口。
方向代理指的是以代理服務器來接收Internet上的鏈接請求,而後將請求轉發給內部網絡上的服務器, 而且將服務器返回的結果發送給客戶端。
關於反向代理的更多內容,建議你閱讀這篇文章。
解釋:這個問題用於檢查被面試者是否有實際運行Node應用的經驗。
Node採用的是單線程的處理機制(全部的I/O請求都採用非阻塞的工做方式),至少從Node.js開發者的角度是這樣的。 而在底層,Node.js藉助libuv來做爲抽象封裝層, 從而屏蔽不一樣操做系統的差別,Node能夠藉助livuv來來實現多線程。下圖表示了Node和libuv的關係。
Libuv庫負責Node API的執行。它將不一樣的任務分配給不一樣的線程,造成一個事件循環, 以異步的方式將任務的執行結果返回給V8引擎。能夠簡單用下面這張圖來表示。
每個I/O都須要一個回調函數——一旦執行完便推到事件循環上用於執行。 若是你須要更多詳細的解釋,能夠參考這個視頻。 你也能夠參考這篇文章。
解釋:這用於檢查Node.js的底層知識,例如什麼是libuv,它的做用是什麼。
Event Loop: http://www.ruanyifeng.com/blog/2014/10/event-loop.html
你能夠選擇以下的工具:
在團隊開發中,這些工具對於編寫代碼很是的有幫助,可以幫助團隊開發者強制執行規定的風格指南, 還可以經過靜態分析捕獲常見的錯誤。
解析:用於檢查被面試者是否有大型項目開發經驗。
經過NPM,你能夠安裝和管理項目的依賴,而且可以指明依賴項的具體版本號。 對於Node應用開發而言,你能夠經過package.json文件來管理項目信息,配置腳本, 以及指明項目依賴的具體版本。
關於NPM的更多信息,你能夠參考官方文檔。
解析:它能考察面試者使用npm命令的基礎知識和Node.js開發的實際經驗。
Stub是用於模擬一個組件或模塊的函數或程序。在測試用例中, 簡單的說,你能夠用Stub去模擬一個方法,從而避免調用真實的方法, 使用Stub你還能夠返回虛構的結果。你能夠配合斷言使用Stub。
舉個例子,在一個讀取文件的場景中,當你不想讀取一個真正的文件時:
var fs = require('fs'); var readFileStub = sinon.stub(fs, 'readFile', function (path, cb) { return cb(null, 'filecontent'); }); expect(readFileStub).to.be.called; readFileStub.restore();
在單元測試中:Stub是徹底模擬一個外部依賴,而Mock經常使用來判斷測試經過仍是失敗。
有關Node.js的單元測試小結,你能夠參考這個連接。
解析:用於測試被面試者是否有測試的經驗。若是被面試者知道什麼是Stub, 那麼能夠繼續問他是如何作單元測試的。
測試金字塔指的是: 當咱們在編寫測試用例時,底層的單元測試應該遠比上層的端到端測試要多。
當咱們談到HTTP API時,咱們可能會涉及到:
有不少針對模型的底層單元測試
但你須要測試模型間如何交互時,須要減小集成測試
解析:本文主要考察被面試者的在測試方面的經驗。
這題沒有惟一的答案。本題主要考察被面試者對於他所使用的Node框架的理解程度, 考察他是否可以給出選擇該框架的理由,優缺點等。經常使用的HTTP框架你能夠參考這個網站。
Statement
原文地址:https://blog.risingstack.com/node-js-interview-questions