Node.js文檔

# 模塊機(jī)制

node采用模塊化結(jié)構(gòu)冯丙,按照CommonJS規(guī)范定義和使用模塊,模塊與文件是一一對(duì)應(yīng)關(guān)系援雇,即加載一個(gè)模塊裕循,實(shí)際上就是加載對(duì)應(yīng)的一個(gè)模塊文件

node 的基礎(chǔ)中毫無疑問的應(yīng)該是有關(guān)于模塊機(jī)制的方面的,也即require這個(gè)內(nèi)置功能的一些原理娇昙,關(guān)于模塊互相引用的推薦先好好讀讀官方文檔尺迂,在

這里就不給大家詳細(xì)解釋了

# 熱更新

從面試官的角度看, 熱更新 是很多程序常見的問題,對(duì)客戶端而言噪裕,熱更新意味著不用換包蹲盘,當(dāng)然也包含著md5校驗(yàn)/差異更新等。復(fù)雜問題:

對(duì)服務(wù)端而言膳音,熱更新意味著服務(wù)不用重啟召衔,這樣可用性較高。

在node中做熱更新代碼祭陷,牽扯到的知識(shí)點(diǎn)可能主要是require會(huì)有一個(gè)cache苍凛,有這個(gè)cache在,即使你更新了 .js文件兵志,在

代碼中再次require還是會(huì)拿到之前的編譯好緩存在v8內(nèi)存(code space)中的舊代碼毫深,但是如果只是淡出的清除掉require中的cache,再次

require確實(shí)能拿到新的代碼毒姨,但是這時(shí)候很容易碰到各地維持舊的引用依舊跑的舊的代碼的問題哑蔫。

不過熱更新json之類的配置文件的話,還是可以簡單的實(shí)現(xiàn)弧呐,更新require的cache就行闸迷,不會(huì)

有持有舊引用的問題,但是舊的引用一直被持有很容易出現(xiàn)內(nèi)從泄露俘枫,而要熱更新配置的話腥沽,為什么不存數(shù)據(jù)庫?或者使用zookeeper之類

的服務(wù)鸠蚪?通過更新文件還要在發(fā)布一次今阳,但是存數(shù)據(jù)庫直接寫個(gè)接口配個(gè)頁面多爽

# 上下文

對(duì)于node.js而言,正常情況下只有一個(gè)上下文茅信,甚至于內(nèi)置的很多方面例如 require的實(shí)現(xiàn)只是在啟動(dòng)的時(shí)候運(yùn)行了內(nèi)置的函數(shù)

每個(gè)單獨(dú)的.js文件并不意味著單獨(dú)的上下文盾舌,在某個(gè).js文件中污染了全局的作用域一樣能影響到其它的地方

而目前的node.js將VM的接口暴露了出來,可以讓你自己創(chuàng)建一個(gè)新的js上下文蘸鲸,這一點(diǎn)上跟前端還是區(qū)別挺大的妖谴,在執(zhí)行外部代碼的

時(shí)候,通過創(chuàng)建新的上下文沙盒(sandbox)可以避免上下文被污染

'use strict';

const vm = require('vm');

let code =

`(function(require) {

const http = require('http');

http.createServer( (request, response) => {

response.writeHead(200, {'Content-Type': 'text/plain'});

response.end('Hello World\\n');

}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

})`;

vm.runInThisContext(code)(require);

問題:既然可以通過新的上下文來避免污染酌摇,那么為什么 node.js不給每一個(gè).js文件以獨(dú)立的上下文來避免作用域被污染

問題其實(shí)有點(diǎn)下套膝舅,其實(shí)Node有給每個(gè)js文件獨(dú)立的上下文,但是這避免不了全局的作用域污染窑多,實(shí)際上這是為了功能的妥協(xié)仍稀。

Node.js 模塊正常情況對(duì)作用域不會(huì)造成污染,意外創(chuàng)建全局變量是一種例外埂息,可以采用嚴(yán)格模式來避免

# 包管理

------------------------------------------------------

1. a.js和b.js兩個(gè)文件互相require是否會(huì)死循環(huán)技潘?雙方是否能導(dǎo)出變量遥巴?如何從設(shè)計(jì)上避免這種問題?

答:不會(huì)崭篡,先執(zhí)行的導(dǎo)出空對(duì)象挪哄,通過導(dǎo)出工廠函數(shù)讓對(duì)方從函數(shù)去拿比較好避免。

模塊在導(dǎo)出的只是 var module = { exports: {}};中的exports琉闪,以從a.js啟動(dòng)為例迹炼,a.js還沒執(zhí)行完exports就是{} 在b.js的開頭拿到的就是 {} 而已。

另外還有非车弑校基礎(chǔ)和常見的問題斯入,比如:module.exports和exports的區(qū)別這里也能一并解決了,exports只是module.exports的一個(gè)引用

2. 如果a.js require了b.js蛀蜜,那么在b中定義的全局變量t=11能否在a中直接打印出來刻两?

答:每個(gè).js能獨(dú)立一個(gè)環(huán)境只是因?yàn)閚ode幫你在外層包了一圈自執(zhí)行,所以你使用 t=11 定義全局變量在其它地方當(dāng)然能拿到滴某,情況如下:

//b.js

(function (exports,require,module,__filename,__dirname){

t=11;

})();

//a.js

(function (exports,require,nodule,__filename,__dirname){

console.log(t);//11

})();

3. 如何在不重啟node進(jìn)程的情況下熱更新一個(gè)js/json文件磅摹?這個(gè)問題本身是否有問題?

答:可以清除掉require的緩存? 重新require(),視具體情況還可以用VM模塊重新執(zhí)行霎奢。當(dāng)然這個(gè)問題可能是典型的X-Y Problem户誓,使用js實(shí)現(xiàn)熱更新很容易碰到v8優(yōu)化之后各地拿到緩存的引用導(dǎo)致熱更新js沒意義,當(dāng)然熱更新json還是可以簡單一點(diǎn)比如用讀取文件的方式來熱更新幕侠,但是這樣也不如從redis之類的數(shù)據(jù)庫中讀取比較合理

4. 比較 AMD, CMD, CommonJS 三者的區(qū)別帝美?

AMD,CMD,CommonJS是目前最常用的三種模塊化書寫規(guī)范。

commonjs是用在服務(wù)器端的晤硕,同步的悼潭,如nodejs

amd, cmd是用在瀏覽器端的,異步的舞箍,如requirejs和seajs

其中舰褪,amd先提出,cmd是根據(jù)commonjs和amd基礎(chǔ)上提出的创译。

根據(jù)CommonJS規(guī)范抵知,一個(gè)單獨(dú)的文件就是一個(gè)模塊。加載模塊使用require方法软族,該方法讀取一個(gè)文件并執(zhí)行,最后返回文件內(nèi)部的exports對(duì)象残制。 CommonJS 加載模塊是同步的立砸,所以只有加載完成才能執(zhí)行后面的操作。像Node.js主要用于服務(wù)器的編程初茶,加載的模塊文件一般都已經(jīng)存在本地硬盤颗祝,所以加載起來比較快,不用考慮異步加載的方式,所以CommonJS規(guī)范比較適用螺戳。但如果是瀏覽器環(huán)境搁宾,要從服務(wù)器加載模塊,這是就必須采用異步模式倔幼。所以就有了 AMD? CMD 解決方案盖腿。

AMD 是 RequireJS 在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出

AMD異步加載模塊。它的模塊支持對(duì)象 函數(shù) 構(gòu)造器 字符串 JSON等各種類型的模塊损同。

適用AMD規(guī)范適用define方法定義模塊翩腐。

CMD是SeaJS 在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出

CMD和AMD的區(qū)別有以下幾點(diǎn):

1.對(duì)于依賴的模塊AMD是提前執(zhí)行,CMD是延遲執(zhí)行膏燃。不過RequireJS從2.0開始茂卦,也改成可以延遲執(zhí)行(根據(jù)寫法不同,處理方式不通過)组哩。

2.CMD推崇依賴就近等龙,AMD推崇依賴前置。

3.AMD的api默認(rèn)是一個(gè)當(dāng)多個(gè)用伶贰,CMD嚴(yán)格的區(qū)分推崇職責(zé)單一蛛砰。例如:AMD里require分全局的和局部的。CMD里面沒有全局的 require,提供 seajs.use()來實(shí)現(xiàn)模塊系統(tǒng)的加載啟動(dòng)幕袱。CMD里每個(gè)API都簡單純粹暴备。

5. 關(guān)于 node 中 require 的實(shí)現(xiàn)原理等

答:require原生入口代碼里面調(diào)用了__load方法用于加載文件,繼續(xù)看__load方法原生代碼里面調(diào)用了_resolveFilename方法们豌,顧名思義涯捻,這應(yīng)該是一個(gè)解析需要require的文件名的方法,繼續(xù)看_resolveFilename方法中又調(diào)用了_findPath方法望迎。

可以看到障癌,這里完整的顯示了node是如何根據(jù)require傳入的名稱來定位具體的文件的,他們的順序依次是:

1辩尊、先從緩存中讀取涛浙,如果沒有則繼續(xù)往下

2、判斷需要模塊路徑是否以/結(jié)尾摄欲,如果不是轿亮,則要判斷

a. 檢查是否是一個(gè)文件,如果是胸墙,則轉(zhuǎn)換為真實(shí)路徑

b. 否則如果是一個(gè)目錄我注,則調(diào)用tryPackage方法讀取該目錄下的package.json文件,把里面的main屬性設(shè)置為filename

c. 如果沒有讀到路徑上的文件迟隅,則通過tryExtensions嘗試在該路徑后依次加上.js但骨,.json和.node后綴励七,判斷是否存在,若存在則返回加上后綴后的路徑

3奔缠、如果依然不存在掠抬,則同樣調(diào)用tryPackage方法讀取該目錄下的package.json文件,把里面的main屬性設(shè)置為filename

4校哎、如果依然不存在两波,則嘗試在該路徑后依次加上index.js,index.json和index.node贬蛙,判斷是否存在雨女,若存在則返回拼接后的路徑。

5阳准、若解析成功氛堕,則把解析得到的文件名cache起來,下次require就不用再次解析了野蝇,否則若解析失敗讼稚,則返回false

------------------------

# Promise

Promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案--回調(diào)函數(shù)和事件--更合理和更前大

所謂Promise绕沈,簡單說就是一個(gè)容器锐想,里面保存著某個(gè)未來才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果,從語法上說乍狐,Promise是一個(gè)對(duì)象赠摇,從他可以獲取異步操作的消息,Promise提供統(tǒng)一的API浅蚪,各種異步操作都可以用同樣的方法進(jìn)行處理

有了Promise對(duì)象藕帜,就可以將異步操作以同步操作的方式表達(dá)出來,避免層層嵌套的回調(diào)函數(shù)

Promise對(duì)象的兩個(gè)特點(diǎn):

1.對(duì)象的狀態(tài)不受外界影響

Promise對(duì)象代表一個(gè)異步操作惜傲,有三種狀態(tài):pending(進(jìn)行中)洽故,fulfilled(已成功),rejected(已失敗)盗誊,只有異步操作的結(jié)果时甚,可以決定當(dāng)前是哪一種狀態(tài),任何其它操作都無法改變這個(gè)狀態(tài)哈踱。這也是Promise這個(gè)名字的由來荒适,它的英語意思就是“承諾”,表示其它手段無法改變

2.一旦狀態(tài)改變,就不會(huì)再變开镣,任何時(shí)候都可以得到這個(gè)結(jié)果

resolved(已定型)

promise對(duì)象的狀態(tài)改變只有兩種可能:從pending變?yōu)閒ulfilled和從pending變?yōu)閞ejected吻贿,只要這兩種情況發(fā)生,狀態(tài)就凝固了哑子,不會(huì)再變了舅列,會(huì)一直保持這個(gè)結(jié)果,這時(shí)稱為已定型

缺點(diǎn):

首先卧蜓,無法取消Promise帐要,一旦新建它就會(huì)立即執(zhí)行,無法中途取消弥奸。

其次榨惠,如果不設(shè)置回調(diào)函數(shù),promise內(nèi)部拋出的錯(cuò)誤盛霎,不會(huì)反應(yīng)到外部

當(dāng)處于pending狀態(tài)時(shí)赠橙,無法得知目前進(jìn)展到哪一個(gè)階段

# Events(事件)

# Timers(定時(shí)器)

# 阻塞/異步

# 并行/并發(fā)

1. Promise 中 .then的第二個(gè)參數(shù)與.catch 有什么區(qū)別?

沒什么多大的區(qū)別愤炸,全都是用來處理錯(cuò)誤函數(shù)的

詳情可參考:http://es6.ruanyifeng.com/#docs/promise

2. Eventemitter的emit是同步還是異步

Node.js 中 Eventemitter 的 emit 是同步的

按監(jiān)聽器的注冊(cè)順序期揪,同步地調(diào)用每個(gè)注冊(cè)到名為 eventName 事件的監(jiān)聽器,并傳入提供的參數(shù)规个。

如果事件有監(jiān)聽器凤薛,則返回 true ,否則返回 false诞仓。

3. 如何判斷接口是否異步缤苫?是否只要有回調(diào)函數(shù)就是異步?

異步:發(fā)出指令墅拭,然后去做別的事情了活玲,所有操作完成后再執(zhí)行回調(diào)

異步I/O:異步的發(fā)出I/O請(qǐng)求

看文檔

console.log 打印看看

看是否有 IO 操作

單純使用回調(diào)函數(shù)并不會(huì)異步, IO 操作才可能會(huì)異步, 除此之外還有使用 setTimeout 等方式實(shí)現(xiàn)異步.

4. nextTick,setTimeout以及setImmediate三者的區(qū)別?

5. 如何實(shí)現(xiàn)一個(gè)sleep函數(shù)谍婉?

function sleep(ms) {

var start = Date.now(), expire = start + ms;

while (Date.now() < expire) ;

return;

}

6. 如何實(shí)現(xiàn)一個(gè)異步的reduce舒憾?(在Es5中出現(xiàn)的數(shù)組方法)

需要了解 reduce 的情況, 是第 n 個(gè)與 n+1 的結(jié)果異步處理完之后, 在用新的結(jié)果與第 n+2 個(gè)元素繼續(xù)依次異步下去

# 進(jìn)程

## Process(進(jìn)程)

## Child Processes(子進(jìn)程)

## Cluster(集群)

## 進(jìn)程間通信

## 守護(hù)進(jìn)程

1. 進(jìn)程的當(dāng)前工作目錄是什么?有什么作用屡萤?

2. child_process.fork與POSIX的fork有什么區(qū)別珍剑?

cluster是常見的node利用多核的方法,它是基于child_process.fork()實(shí)現(xiàn)的,所以cluster產(chǎn)生的進(jìn)程之間是通過IPC來通信的死陆,并且它也沒有拷貝父進(jìn)程的空間招拙,而是通過加入cluster.isMaster這個(gè)標(biāo)識(shí),來區(qū)分父進(jìn)程以及子進(jìn)程措译,達(dá)到類似POSIX的fork效果

3. 父進(jìn)程或子進(jìn)程的死亡是否回影響對(duì)方别凤?什么是孤兒進(jìn)程?

子進(jìn)程的死亡不會(huì)影響父進(jìn)程领虹,不過子進(jìn)程死亡時(shí)(線程組的最后一個(gè)線程规哪,通常是‘領(lǐng)頭線程死亡時(shí)’)會(huì)向他的父進(jìn)程發(fā)送死亡信號(hào)。反之父進(jìn)程死亡塌衰,一般情況下子進(jìn)程也會(huì)隨之死亡诉稍,但如果此時(shí)子進(jìn)程處于可運(yùn)狀態(tài)蝠嘉,僵死狀態(tài)等等的話,子進(jìn)程將被進(jìn)程1(init進(jìn)程)收養(yǎng)杯巨,從而成為孤兒進(jìn)程蚤告。

子進(jìn)程死亡的時(shí)候(處于‘終止?fàn)顟B(tài)’),父進(jìn)程沒有及時(shí)調(diào)用wait()或waitpid()來返回死亡進(jìn)程的相關(guān)信息,此時(shí)子進(jìn)程還有一個(gè)PCB殘留在進(jìn)程表中服爷,被稱為僵尸進(jìn)程杜恰。

4. cluster是如何保證負(fù)載均衡的?

5. 什么是守護(hù)進(jìn)程仍源?如何實(shí)現(xiàn)守護(hù)進(jìn)程心褐?

守護(hù)進(jìn)程,是服務(wù)端方面一個(gè)很基礎(chǔ)的概念笼踩。很多人只知道通過pm2之類的工具可以將進(jìn)程以守護(hù)進(jìn)程的方式啟動(dòng)逗爹,卻不了解什么是守護(hù)進(jìn)程,為什么要使用守護(hù)進(jìn)程

普通的進(jìn)程戳表,在用戶退出終端之后就會(huì)直接關(guān)閉桶至,通過&啟動(dòng)到后臺(tái)的進(jìn)程,之后會(huì)由于會(huì)話(session組)被回收而終止進(jìn)程匾旭,守護(hù)進(jìn)程是不依賴終端(tty)的進(jìn)程镣屹,不會(huì)因?yàn)橛脩敉顺鼋K端而停止運(yùn)行的進(jìn)程

# IO

# Buffer

# String Decoder(字符串解碼)

# Stream (流)

# Console (控制臺(tái))

# File System (文件系統(tǒng))

# Readline

# REPL

1.Buffer一般處理什么數(shù)據(jù)?其長度能否動(dòng)態(tài)變化价涝?

Buffer是node.js中用于處理二進(jìn)制數(shù)據(jù)的類女蜈,其中與IO相關(guān)的操作(網(wǎng)絡(luò)/文件等)均基于Buffer,Buffer類的實(shí)例非常類似整數(shù)數(shù)組

但其大小是固定不變的色瘩,并且其內(nèi)存在V8堆棧外分配原始內(nèi)存空間伪窖。Buffer類的實(shí)例創(chuàng)建之后,其所占用的內(nèi)存大小不能再進(jìn)行調(diào)整

2.Stream的highWaterMark與drain事件是什么居兆?二者之間的關(guān)系是覆山?

3.Stream的pipe的作用是?在pipe的過程中數(shù)據(jù)是引用傳遞還是拷貝傳遞泥栖?

將一個(gè)可寫流附到可讀流上簇宽,同時(shí)將可寫切換到流模式,并把所有數(shù)據(jù)推給可寫流吧享,在pipe傳遞數(shù)據(jù)的過程中魏割,objectMode是傳遞引用,非objectMode則是拷貝一份數(shù)據(jù)傳遞下去

4.什么是文件描述符钢颂?輸入流钞它,輸出流,錯(cuò)誤流是什么?

5.console.log是同步還是異步遭垛?如何實(shí)現(xiàn)一個(gè)console.log?

console.log正常情況下是異步的尼桶,除非你使用new Console(stdout[,stderr])指定了一個(gè)文件的目的地

let print = (str) =>? process.stdout.write(str + '\n')

print('hello world')

6.如何同步的獲取用戶的輸入?

node中耻卡,獲取用戶的輸入其實(shí)就是讀取node進(jìn)程中的輸入流的數(shù)據(jù)

而要同步讀取疯汁,則是不用異步的read接口,而是用同步的readSync接口去讀取stdin的數(shù)據(jù)可實(shí)現(xiàn)

7.Readline是如何實(shí)現(xiàn)的卵酪?

readline模塊提供了一個(gè)用于從Readble的stream中一次讀取一行的接口,當(dāng)然你也可以用于讀取文件或net,http,stream.

實(shí)現(xiàn)上谤碳,readline在讀取TTY的數(shù)據(jù)時(shí)溃卡,是通過input.on('keypress','onkeypress')時(shí)發(fā)現(xiàn)用戶按下了回車鍵來判斷是新的line的,而讀取一般的stream時(shí)蜒简,則是通過緩存數(shù)據(jù)然后用正則,test來判斷是否為new line

8.REPL

Read--Eval--Print--Loop(交互式解釋器)

repl模塊提供了一種‘讀取--求值-輸出-循環(huán)的實(shí)現(xiàn)’它可以作為一個(gè)獨(dú)立的程序或嵌入到其它應(yīng)用中

9.Cluster模塊

node默認(rèn)單線程進(jìn)行瘸羡,對(duì)于32位系統(tǒng)最高可以使用512MB內(nèi)存,對(duì)于64位最高可以使用1GB內(nèi)存搓茬。對(duì)于多核CPU的計(jì)算機(jī)來說犹赖,這樣做效率很低,因?yàn)橹挥幸粋€(gè)核在運(yùn)行卷仑,其它核都在閑置峻村。cluster模塊就是為解決這個(gè)問題而提出的

Cluster模塊允許建立一個(gè)主進(jìn)程和若干個(gè)worker進(jìn)程,由主進(jìn)程監(jiān)控和協(xié)調(diào)worker進(jìn)程的運(yùn)行锡凝,worker之間采用進(jìn)程間通信交換信息粘昨,cluster模塊內(nèi)置一個(gè)負(fù)載均衡器,采用Round-robin算法協(xié)調(diào)各個(gè)worker進(jìn)程之間的負(fù)載窜锯,運(yùn)行時(shí)张肾,所有新建立的鏈接都有主進(jìn)程完成,然后主進(jìn)程再把TCP連接分配給指定的worker進(jìn)程

10. Events模塊

回調(diào)函數(shù)模式讓node可以處理異步操作锚扎,但是洞翩,為了適應(yīng)回調(diào)函數(shù),異步操作只能有兩個(gè)狀態(tài):開始和結(jié)束坯癣。對(duì)于那些多狀態(tài)的異步操作炸庞,回調(diào)函數(shù)就會(huì)無法處理,你不得不將異步操作拆開助币,分成多個(gè)階段浪听,每個(gè)階段結(jié)束時(shí),調(diào)用下一個(gè)回調(diào)函數(shù)眉菱。

為了解決這個(gè)問題迹栓,node提供Event Emitter接口。通過事件俭缓,解決多狀態(tài)異步操作的響應(yīng)問題

11. child_process模塊

用于新建子進(jìn)程克伊,子進(jìn)程的運(yùn)行結(jié)果儲(chǔ)存在系統(tǒng)緩存之中(最大200KB)酥郭,等到子進(jìn)程運(yùn)行結(jié)束后,主進(jìn)程在調(diào)用回調(diào)函數(shù)讀取子進(jìn)程的運(yùn)行結(jié)果

#小題型

1. 什么是error-first回調(diào)模式愿吹?

錯(cuò)誤優(yōu)先處理回調(diào)函數(shù)不从,應(yīng)用error-first回調(diào)模式是為了更好的進(jìn)行錯(cuò)誤和數(shù)據(jù)的傳遞,第一個(gè)參數(shù)保留給一個(gè)錯(cuò)誤error對(duì)象犁跪,一旦出現(xiàn)錯(cuò)誤椿息,錯(cuò)誤將通過第一個(gè)參數(shù)error返回。其余的參數(shù)將用作數(shù)據(jù)的傳遞坷衍。

2. 如何避免回調(diào)地獄寝优?

模塊化設(shè)計(jì):將回調(diào)函數(shù)拆分成幾個(gè)獨(dú)立的函數(shù)

使用流程控制庫,比如async

組合使用generators和Promises

使用async/await函數(shù)

3. 什么是Promises枫耳?

在 then 后沒有 catch 乏矾,沒有捕捉異常。這樣做會(huì)造成故障沉默迁杨,不會(huì)拋出異常钻心。

如果你調(diào)試一個(gè)巨大的代碼庫,并且比不知道哪個(gè) Promise 函數(shù)有潛在的問題, 你可以使用

unhandledRejection 這個(gè)工具铅协。它將會(huì)打印出所有未處理的 reject 狀態(tài)的 Promise捷沸。

4. 什么工具統(tǒng)一團(tuán)隊(duì)的代碼風(fēng)格?為什么統(tǒng)一的代碼風(fēng)格很重要警医?

ESLint和Standard可以用來統(tǒng)一代碼

因?yàn)閳F(tuán)隊(duì)協(xié)作時(shí)亿胸,代碼風(fēng)格一致,團(tuán)隊(duì)成員可以更輕松的構(gòu)建項(xiàng)目预皇,可以通過靜態(tài)分析排除代碼問題

5. 什么時(shí)候用npm侈玄?什么時(shí)候應(yīng)當(dāng)用yarn?

6. 什么是樁代碼(stub)吟温?請(qǐng)描述一下應(yīng)用場景序仙?

樁代碼就是在某些組件或模塊中,模擬某些功能的代碼鲁豪。樁代碼的作用是占位潘悼,讓代碼在測(cè)試過程中順利進(jìn)行,測(cè)試時(shí)爬橡,stub可以為函數(shù)調(diào)用返回模擬的結(jié)果治唤,比如,當(dāng)我們寫文件時(shí)糙申,實(shí)際上并不需要真正去寫

7. 什么是測(cè)試金字塔宾添?請(qǐng)舉例說明?

測(cè)試金字塔反映了單元測(cè)試,集成測(cè)試缕陕,端到端測(cè)試在測(cè)試中占的比例

8. 你最欣賞的HTTP框架是什么粱锐?為什么?

9. 如何保證你的cookie安全扛邑?如何阻止XSS攻擊怜浅?

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

HttpOnly 這個(gè)屬性幫助防止跨站腳本攻擊,它禁止通過JavaScript訪問cookie

為了防止攻擊蔬崩,可以對(duì)HTTP header里的set-cookie進(jìn)行處理set-cookie:sid=;HttpOnly.

如果使用express框架恶座,可以使用express-cookie session,它會(huì)默認(rèn)做出上述防止XSS攻擊的設(shè)置

10. 如何確認(rèn)項(xiàng)目的相關(guān)依賴安全舱殿?

自動(dòng)的更新你的依賴: npm outdated

NSP

11. 什么時(shí)候應(yīng)該在后臺(tái)進(jìn)程中使用消息服務(wù)奥裸,怎樣處理工作想成的任務(wù)/怎么給worker安排任務(wù)?

消息隊(duì)列適用于后臺(tái)數(shù)據(jù)傳輸服務(wù)沪袭,比如發(fā)送郵件和數(shù)據(jù)圖像處理

消息隊(duì)列有很多解決方案,比如RabbitMQQ

12. 這段代碼有什么問題樟氢?

new? Promise((resolve,reject) => {

throw new Error('error')

})

.then(console.log)

then之后沒有catch冈绊。這樣的話,錯(cuò)誤會(huì)被忽略埠啃,會(huì)造成故障沉默

后邊跟上 .catch(console.error)

調(diào)試一個(gè)大型項(xiàng)目時(shí)死宣,可以使用監(jiān)控unhandleRejection事件來捕獲所有未處理的Promise錯(cuò)誤

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

console.log(err)

})

13. 這段代碼輸出什么?

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.創(chuàng)建promise毅该,resolve的值為1

2.x 的值為1,加1 返回2

3.x 的值為2潦牛,但是沒有用到眶掌,拋出一個(gè)錯(cuò)誤

4.捕獲錯(cuò)誤,但是沒有處理巴碗,返回1

5.x 的值為1朴爬,加1 返回2

6.x 的值為2,打印為2

7.不會(huì)執(zhí)行橡淆,因?yàn)闆]有錯(cuò)誤拋出

14.為什么要用node召噩?

簡單強(qiáng)大,輕量可擴(kuò)展

簡單體現(xiàn)在node使用JavaScript逸爵,json來進(jìn)行編碼具滴,人人都會(huì)

強(qiáng)大體現(xiàn)在非阻塞IO,可以適應(yīng)分塊傳輸數(shù)據(jù)师倔,較慢的網(wǎng)絡(luò)環(huán)境构韵,尤其擅長高并發(fā)訪問。

輕量體現(xiàn)在node本身既是代碼,又是服務(wù)器贞绳,前后端使用統(tǒng)一語言谷醉。

可擴(kuò)展體現(xiàn)在可以輕松應(yīng)對(duì)多實(shí)例,多服務(wù)架構(gòu)冈闭,同時(shí)有海量的第三方應(yīng)用組件

node的優(yōu)點(diǎn):I/O密集型處理是node的強(qiáng)項(xiàng)俱尼,因?yàn)閚ode的I/O請(qǐng)求都是異步的

node的缺點(diǎn):不擅長CPU密集型的操作

CPU密集型操作(復(fù)雜的運(yùn)算,圖片的操作)

15. node的架構(gòu)是什么樣子的萎攒?

主要分為三層遇八,應(yīng)用app >> v8及node內(nèi)置架構(gòu) >> 操作系統(tǒng)

v8是node運(yùn)行的環(huán)境,可以理解為node虛擬機(jī)

node內(nèi)置架構(gòu)又可分為三層:

核心模塊(javascript實(shí)現(xiàn)) >> c++綁定 >> libuv + CAes + http

16. node有哪些核心模塊耍休?

EventEmitter刃永,Stream,F(xiàn)S羊精,Net和全局對(duì)象

17. node在企業(yè)中常用到斯够?

靜態(tài)資源服務(wù)器,代碼本地構(gòu)建喧锦,單元測(cè)試读规,UI測(cè)試

工作中應(yīng)該注意:精確版本號(hào),測(cè)試燃少,使用debug束亏,保持代碼精簡

多請(qǐng)教,保持獨(dú)立思考阵具,使用現(xiàn)有的庫碍遍,保持簡單

良好的文檔,配置文件阳液,使用pm2

libuv:提供異步功能的C庫怕敬。它在運(yùn)行是負(fù)責(zé)一個(gè)事件循環(huán)(Event loop),一個(gè)線程池,文件系統(tǒng)I/O,DNS相關(guān)和網(wǎng)絡(luò)I/O,以及其它一些功能

18. node異常處理

node是單線程運(yùn)行環(huán)境趁舀,一旦拋出的異常沒有被捕獲就會(huì)引起整個(gè)進(jìn)程的崩潰赖捌。

使用throw語句拋出一個(gè)錯(cuò)誤對(duì)象,即拋出異常

將錯(cuò)誤對(duì)象傳遞給回調(diào)函數(shù)矮烹,由回調(diào)函數(shù)負(fù)責(zé)發(fā)出錯(cuò)誤

通過EventEmitter接口越庇,發(fā)出一個(gè)error事件

try...catch結(jié)構(gòu)無法捕獲異步運(yùn)行的代碼拋出的錯(cuò)誤

19. node關(guān)于高并發(fā)問題?

原理:非阻塞事件驅(qū)動(dòng)實(shí)現(xiàn)異步開發(fā)奉狈,通過事件驅(qū)動(dòng)的I/O來操作完成跨平臺(tái)數(shù)據(jù)密集型實(shí)時(shí)應(yīng)用

傳統(tǒng)的server每個(gè)請(qǐng)求生成一個(gè)線程卤唉,node是一個(gè)單線程的,使用libuv保持?jǐn)?shù)萬并發(fā)

libuv原理:

c語言編寫的基礎(chǔ)庫實(shí)現(xiàn)主循環(huán)仁期,文件桑驱,網(wǎng)絡(luò)即可

libuv的改進(jìn):

回傳上下文信息

其它線程不能訪問缺省主循環(huán)竭恬,loop不支持多線程

數(shù)據(jù)庫高并發(fā)實(shí)現(xiàn)

var proxy = new EventProxy();

var status = "ready";

var select = function(callback){

proxy.once("selected",callback);

if(status == "ready"){

status = "pending";

db.select("SQL", function(results){

proxy.emit("selected",results);

status = "ready";

});

}

20. 什么是異步?

異步就是發(fā)出操作指令(把回調(diào)函數(shù)加入異步隊(duì)列)熬的,然后就可以去做別的事情去了痊硕,所有操作完成后再執(zhí)行回調(diào)

異步I/O就是異步的發(fā)出I/O請(qǐng)求

雖然node可以異步發(fā)出I/O請(qǐng)求,但nodejs不支持多線程押框,為啥就可以支持高并發(fā)呢岔绸?

因?yàn)閚odejs的I/O操作,底層是開啟了多線程的

當(dāng)同時(shí)有多個(gè)I/O請(qǐng)求時(shí)橡伞,主線程會(huì)創(chuàng)建多個(gè)eio線程盒揉,以提高IO請(qǐng)求的處理速度

雖然nodeJS的IO操作開啟了多線程,但是所有線程都是基于主線程開啟的只能跑在一個(gè)進(jìn)程當(dāng)中還是不能充分利用CPU資源

pm2進(jìn)程管理器可以解決這個(gè)問題兑徘,pm2是一個(gè)帶有負(fù)載均衡功能的node應(yīng)用的進(jìn)程管理器

cluster模塊

21. 代碼可讀性維護(hù)改進(jìn)

async:async.waterfall([getcatalog,getaticle,getTigle])

promise的方法

koa寫法

es6寫法使用yield

22.優(yōu)化問題

前端優(yōu)化問題:移除iscorll,合并請(qǐng)求,tcp優(yōu)化刚盈,HTTP優(yōu)化,localstorate挂脑,html5離線緩存

api優(yōu)化:restfulapi,標(biāo)準(zhǔn)輸入輸出

ui優(yōu)化:使用同一的框架藕漱,前端組件化

異常處理:log監(jiān)控,避免大文件處理崭闲,retry處理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谴分,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子镀脂,更是在濱河造成了極大的恐慌,老刑警劉巖忘伞,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件薄翅,死亡現(xiàn)場離奇詭異,居然都是意外死亡氓奈,警方通過查閱死者的電腦和手機(jī)翘魄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舀奶,“玉大人暑竟,你說我怎么就攤上這事∮祝” “怎么了但荤?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長涧至。 經(jīng)常有香客問我腹躁,道長,這世上最難降的妖魔是什么南蓬? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任纺非,我火速辦了婚禮哑了,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘烧颖。我一直安慰自己弱左,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布炕淮。 她就那樣靜靜地躺著拆火,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鳖悠。 梳的紋絲不亂的頭發(fā)上榜掌,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音乘综,去河邊找鬼憎账。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卡辰,可吹牛的內(nèi)容都是我干的胞皱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼九妈,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼反砌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起萌朱,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤宴树,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后晶疼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酒贬,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年翠霍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锭吨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡寒匙,死狀恐怖零如,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锄弱,我是刑警寧澤考蕾,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站棵癣,受9級(jí)特大地震影響辕翰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜狈谊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一喜命、第九天 我趴在偏房一處隱蔽的房頂上張望沟沙。 院中可真熱鬧,春花似錦壁榕、人聲如沸矛紫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颊咬。三九已至,卻和暖如春牡辽,著一層夾襖步出監(jiān)牢的瞬間喳篇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工态辛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留麸澜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓奏黑,卻偏偏與公主長得像炊邦,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子熟史,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • topics: 1.The Node.js philosophy 2.The reactor pattern 3....
    宮若石閱讀 1,057評(píng)論 0 1
  • 1.幾種基本數(shù)據(jù)類型?復(fù)雜數(shù)據(jù)類型?值類型和引用數(shù)據(jù)類型?堆棧數(shù)據(jù)結(jié)構(gòu)? 基本數(shù)據(jù)類型:Undefined馁害、Nul...
    極樂君閱讀 5,498評(píng)論 0 106
  • Node.js是目前非常火熱的技術(shù)蹂匹,但是它的誕生經(jīng)歷卻很奇特碘菜。 眾所周知,在Netscape設(shè)計(jì)出JavaScri...
    w_zhuan閱讀 3,607評(píng)論 2 41
  • Node.js是目前非诚弈火熱的技術(shù)炉媒,但是它的誕生經(jīng)歷卻很奇特。 眾所周知昆烁,在Netscape設(shè)計(jì)出JavaScri...
    Myselfyan閱讀 4,064評(píng)論 2 58
  • 前兩天在家看奧運(yùn),看得熱血沸騰缎岗。我太愛看奧運(yùn)了静尼,會(huì)讓人產(chǎn)生一種神秘的激情,這種激情曾經(jīng)讓我希望從事體育工作传泊,...
    wowo實(shí)驗(yàn)室閱讀 793評(píng)論 0 50