Node.js十問十答

2015年4月于湖南張家界
1、在開發(fā)Node.js的時(shí)候異步的嵌套很麻煩,有人叫回調(diào)地獄或回調(diào)黑洞,如何解決這一問題?

答:promise async await

多層嵌套:

const express = require('express');
const app = express();
const request = require('request');

app.get('/data', function(req, res) {
    request('php地址1', funciton(error, response, body) {
        request('php地址3', function(error, response, body) {
            request('php地址3', function(error, response, body) {
                ...
                res.json({
                    data: body
                })
            })
        })
    })
})

使用async和await:

const express = require('express');
const app = express();
const request = require('request');
const rp = require('request-promise');

app.get('/data', async function(req, res) {
    const result1 = await rp('php地址1');
    const result2 = await rp('php地址2');
    const result3 = await rp('php地址3');
    console.log(result1 + result2 + result3);
})
2、如何解釋Node.js適合IO密集型不適合CPU密集型?

答:

  • CPU密集型:計(jì)算等邏輯判斷的操作,如:壓縮、解壓、加密和解密等。
  • I/O密集型:存取設(shè)備,網(wǎng)絡(luò)設(shè)施的讀取操作,如:文件的存取,http等網(wǎng)絡(luò)操作,數(shù)據(jù)庫操作等。
    Node.js 執(zhí)行是單線程的,如果執(zhí)行 CPU 密集的任務(wù)就會(huì)阻塞后續(xù)代碼,且單線程無法充分利用 CPU 多核資源。而異步 I/O 是多線程的,在工作線程上執(zhí)行,不會(huì)阻塞執(zhí)行線程,執(zhí)行效率更高。
3、畫出Node.js的異步時(shí)間回調(diào)機(jī)制的實(shí)現(xiàn),并解釋原理。

答:如下圖:


Node.js工作流程圖.png

原理:
(1)V8引擎解析JavaScript腳本。
(2)解析后的代碼,調(diào)用Node API。
(3)libuv庫負(fù)責(zé)Node API的執(zhí)行。它將不同的任務(wù)分配給不同的線程,形成一個(gè)Event Loop(事件循環(huán)),以異步的方式將任務(wù)的執(zhí)行結(jié)果返回給V8引擎。
(4)V8引擎再將結(jié)果返回給用戶。

4、開發(fā)一個(gè)完整的Node.js程序,有UI層、service層、DAO層、MODEL層等,我們要在交給QA測試前需要編寫測試用例。測試用例一般遵循測試金字塔(測試金字塔指的是編寫測試用例時(shí),底層的單元測試應(yīng)該永遠(yuǎn)比上層的端到端測試用例要多,如下圖),請問如下三個(gè)階段,都用了什么樣的技術(shù)進(jìn)行測試用例的編寫?
測試金字塔.jpeg

答:

unit 指的是一小塊業(yè)務(wù)邏輯,可以使一個(gè)小組件、一個(gè)小函數(shù)、一個(gè)小類等
通常用karma+jasmine測試
service 主要是用 mocha+chai 異步測試
UI 主要是用 selenium-webdriver或者nightwatch

5、有人說Node.js是玩具,寫錯(cuò)一處整個(gè)網(wǎng)站都掛掉,有什么解決辦法?

答:

① 使用errorHandler處理對應(yīng)的錯(cuò)誤,如404等
② 用SafeRequest替代request
③ 容錯(cuò),PM2 0秒熱啟功能(守護(hù)進(jìn)程)
④ 電話,郵件,日志等出錯(cuò)的通知機(jī)制
⑤ 用process提供了一個(gè)事件uncaughtException進(jìn)行抓取異常進(jìn)行處理

process.on('uncaughtException', function(err){
      console.log(err);
      console.log(err.stack);
});

⑥ 企業(yè)級錯(cuò)誤監(jiān)測產(chǎn)品,如騰訊的bugly

6、寫出知道的HTTP常用請求報(bào)頭,并寫出常見的HTTP status code含義?

答:常用的HTTP請求報(bào)頭(Request Headers)
Accept-Charset:標(biāo)明瀏覽器可以使用的字符集(如ISO-8859-1).
Accept-Encoding:詳細(xì)列出客戶端能處理的編碼類型(gzip,compress是兩種常見的值),一般來講花在解碼上的時(shí)間要遠(yuǎn)遠(yuǎn)小于傳輸?shù)拈_銷。
Accept-Language:在servlet能夠以多種語言生產(chǎn)結(jié)果時(shí),列出客戶程序首選的語言。這個(gè)報(bào)頭的值應(yīng)該是標(biāo)準(zhǔn)語言代碼的一種,比如en, en-us, da等。
Connection:標(biāo)明客戶是否能夠處理持續(xù)性HTTP連接。持續(xù)性(Keep-Alive)是默認(rèn)的選項(xiàng)。
Content-Length:只適用于POST請求,用來給定POST數(shù)據(jù)的大小,以字節(jié)為單位。
Cookie:這個(gè)報(bào)頭向服務(wù)器返回cookie,這些cookie是之前服務(wù)器發(fā)送給瀏覽器的。使用request.getCookies讀取這個(gè)報(bào)頭。
Host:在HTTP1.1中,瀏覽器和其他客戶端程序需要制定這個(gè)報(bào)頭,它標(biāo)明原始URL中給出的主機(jī)名和端口號(hào)。
Use-Agent標(biāo)識(shí)生產(chǎn)請求的瀏覽器或其他客戶端程序,根據(jù)這個(gè)報(bào)頭,可以針對不同類型的瀏覽器返回不同的內(nèi)容。

7、請用Koa2實(shí)現(xiàn)基本的服務(wù)端,并輸出Hello world,且實(shí)現(xiàn)功能測試。

答:代碼如下:

const Koa = require('koa');
const app = new Koa();

app.use(ctx => {
      ctx.body = Hello world'';
}

app.listen(3000);

功能測試代碼:

const app = require('app');
const request = require('supertest').agent(app.listen());

describe('Hello world', function(){
      it('should say "Hello world" ', function(done){
            request
            .get('/')
            .expect(200)
            .expect('Hello world', done);
      })
})
8、描述何種情況下會(huì)造成Node.js的內(nèi)存泄漏,如何檢測?

答:① 全局變量

a = 1;

這種比較簡單的原因,全局變量直接掛在 root 對象上,不會(huì)被清除掉。
② 閉包

function outter(){
    var a = 1;
    return function inner(b){
        console.log(a+b);
    }
}

var outter2 = outter();
outter2(5);

閉包會(huì)引用到父級函數(shù)中的變量,如果閉包未釋放,就會(huì)導(dǎo)致內(nèi)存泄漏。

③ 過大的數(shù)組循環(huán)

var arr=[];
for(var i = 0; i<10000; i++){
    arr.push(i);
}

2個(gè)檢測工具:memwatchheapdump

9、描述一下當(dāng)下新時(shí)代的前端中Node.js的作用及其實(shí)際應(yīng)用?以及一般Node.js項(xiàng)目文件夾的劃分?

答:作用及應(yīng)用:
① 作為數(shù)據(jù)中間代理層,轉(zhuǎn)發(fā)數(shù)據(jù)
② 為前端提供路由
③ 封裝后端接口

文件夾的劃分:
models:請求數(shù)據(jù)
controller:路由配置
public:靜態(tài)資源
views:模板文件
libs:公共文件
config:配置文件
test:測試文件
app.js啟動(dòng)文件

10、瀏覽器緩存機(jī)制。

答:圖片來自:瀏覽器緩存機(jī)制
瀏覽器第一次請求:

瀏覽器第一次請求.jpg

瀏覽器再次請求時(shí):

瀏覽器再次請求.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • Node.js是目前非常火熱的技術(shù),但是它的誕生經(jīng)歷卻很奇特。 眾所周知,在Netscape設(shè)計(jì)出JavaScri...
    Myselfyan閱讀 4,095評論 2 58
  • <a name='html'>HTML</a> Doctype作用?標(biāo)準(zhǔn)模式與兼容模式各有什么區(qū)別? (1)、<...
    clark124閱讀 3,551評論 1 19
  • 文 |半生緇塵 1、 中國人本質(zhì)上他是一個(gè)群體,畢竟祖上也曾是一個(gè)個(gè)部落組成的家庭。 但他們又是有野心且懦弱的,來...
    半生緇塵閱讀 496評論 0 1
  • 對《所謂會(huì)說話,就是會(huì)換位思考》的摘錄分享: 真正好的溝通技巧是轉(zhuǎn)變自己的思維角度,用換位思考來讓對方感到溫暖有趣...
    愛昔閱讀 133評論 0 0