node核心內(nèi)置類庫(事件,流,文件,網(wǎng)絡(luò)等)

  1. 為什么要用node?
    參考答案: 總結(jié)起來node有以下幾個特點:簡單強大,輕量可擴展.簡單體現(xiàn)在node使用的是javascript,json來進行編碼,人人都會;強大體現(xiàn)在非阻塞IO,可以適應(yīng)分塊傳輸數(shù)據(jù),較慢的網(wǎng)絡(luò)環(huán)境,尤其擅長高并發(fā)訪問;輕量體現(xiàn)在node本身既是代碼,又是服務(wù)器,前后端使用統(tǒng)一語言;可擴展體現(xiàn)在可以輕松應(yīng)對多實例,多服務(wù)器架構(gòu),同時有海量的第三方應(yīng)用組件.

  2. node的構(gòu)架是什么樣子的?
    參考答案: 主要分為三層,應(yīng)用app >> V8及node內(nèi)置架構(gòu) >> 操作系統(tǒng). V8是node運行的環(huán)境,可以理解為node虛擬機.node內(nèi)置架構(gòu)又可分為三層: 核心模塊(javascript實現(xiàn)) >> c++綁定 >> libuv + CAes + http.

  3. node有哪些核心模塊?**

參考答案: EventEmitter, Stream, FS, Net和全局對象

node全局對象

  • 1. node有哪些全局對象?

參考答案: process, console, Buffer和exports

  • 2. process有哪些常用方法?

參考答案: process.stdin, process.stdout, process.stderr, process.on, process.env, process.argv, process.arch, process.platform, process.exit

  • 3. console有哪些常用方法?

參考答案: console.log/console.info, console.error/console.warning, console.time/console.timeEnd, console.trace, console.table

  • 4. node有哪些定時功能?

參考答案: setTimeout/clearTimeout, setInterval/clearInterval, setImmediate/clearImmediate, process.nextTick

  • 5. node中的事件循環(huán)是什么樣子的?

參考答案: event loop其實就是一個事件隊列,先加入先執(zhí)行,執(zhí)行完一次隊列,再次循環(huán)遍歷看有沒有新事件加入隊列.執(zhí)行中的叫IO events, setImmediate是在當前隊列立即執(zhí)行,setTimout/setInterval是把執(zhí)行定時到下一個隊列,process.nextTick是在當前執(zhí)行完,下次遍歷前執(zhí)行.所以總體順序是: IO events >> setImmediate >> setTimeout/setInterval >> process.nextTick

  • 6. node中的Buffer如何應(yīng)用?

參考答案: Buffer是用來處理二進制數(shù)據(jù)的,比如圖片,mp3,數(shù)據(jù)庫文件等.Buffer支持各種編碼解碼,二進制字符串互轉(zhuǎn).

EventEmitter

  • 1. 什么是EventEmitter?

參考答案: EventEmitter是node中一個實現(xiàn)觀察者模式的類,主要功能是監(jiān)聽和發(fā)射消息,用于處理多模塊交互問題.

  • 2. 如何實現(xiàn)一個EventEmitter?

參考答案: 主要分三步:定義一個子類,調(diào)用構(gòu)造函數(shù),繼承EventEmitter

代碼演示

    var util = require('util');
    var EventEmitter = require('events').EventEmitter;

    function MyEmitter() {
        EventEmitter.call(this);
    } // 構(gòu)造函數(shù)

    util.inherits(MyEmitter, EventEmitter); // 繼承

    var em = new MyEmitter();
    em.on('hello', function(data) {
        console.log('收到事件hello的數(shù)據(jù):', data);
    }); // 接收事件,并打印到控制臺
    em.emit('hello', 'EventEmitter傳遞消息真方便!');
  • 3. EventEmitter有哪些典型應(yīng)用?

參考答案: 1) 模塊間傳遞消息 2) 回調(diào)函數(shù)內(nèi)外傳遞消息 3) 處理流數(shù)據(jù),因為流是在EventEmitter基礎(chǔ)上實現(xiàn)的. 4) 觀察者模式發(fā)射觸發(fā)機制相關(guān)應(yīng)用

  • 4. 怎么捕獲EventEmitter的錯誤事件?

參考答案: 監(jiān)聽error事件即可.如果有多個EventEmitter,也可以用domain來統(tǒng)一處理錯誤事件.

代碼演示

    var domain = require('domain');
    var myDomain = domain.create();
    myDomain.on('error', function(err){
        console.log('domain接收到的錯誤事件:', err);
    }); // 接收事件并打印
    myDomain.run(function(){
        var emitter1 = new MyEmitter();
        emitter1.emit('error', '錯誤事件來自emitter1');
        emitter2 = new MyEmitter();
        emitter2.emit('error', '錯誤事件來自emitter2');
    });
  • 5. EventEmitter中的newListenser事件有什么用處?

參考答案: newListener可以用來做事件機制的反射,特殊應(yīng)用,事件管理等.當任何on事件添加到EventEmitter時,就會觸發(fā)newListener事件,基于這種模式,我們可以做很多自定義處理.

代碼演示

var emitter3 = new MyEmitter();
emitter3.on('newListener', function(name, listener) {
    console.log("新事件的名字:", name);
    console.log("新事件的代碼:", listener);
    setTimeout(function(){ console.log("我是自定義延時處理機制"); }, 1000);
});
emitter3.on('hello', function(){
    console.log('hello node');
});

Stream

  • 1. 什么是Stream?

參考答案: stream是基于事件EventEmitter的數(shù)據(jù)管理模式.由各種不同的抽象接口組成,主要包括可寫,可讀,可讀寫,可轉(zhuǎn)換等幾種類型.

  • 2. Stream有什么好處?

參考答案: 非阻塞式數(shù)據(jù)處理提升效率,片斷處理節(jié)省內(nèi)存,管道處理方便可擴展等.

  • 3. Stream有哪些典型應(yīng)用?

參考答案: 文件,網(wǎng)絡(luò),數(shù)據(jù)轉(zhuǎn)換,音頻視頻等.

  • 4. 怎么捕獲Stream的錯誤事件?

參考答案: 監(jiān)聽error事件,方法同EventEmitter.

  • 5. 有哪些常用Stream,分別什么時候使用?

參考答案: Readable為可被讀流,在作為輸入數(shù)據(jù)源時使用;Writable為可被寫流,在作為輸出源時使用;Duplex為可讀寫流,它作為輸出源接受被寫入,同時又作為輸入源被后面的流讀出.Transform機制和Duplex一樣,都是雙向流,區(qū)別時Transfrom只需要實現(xiàn)一個函數(shù)_transfrom(chunk, encoding, callback);而Duplex需要分別實現(xiàn)_read(size)函數(shù)和_write(chunk, encoding, callback)函數(shù).

  • 6. 實現(xiàn)一個Writable Stream?

參考答案: 三步走:1)構(gòu)造函數(shù)call Writable 2) 繼承Writable 3) 實現(xiàn)_write(chunk, encoding, callback)函數(shù)

代碼演示

var Writable = require('stream').Writable;
var util = require('util');

function MyWritable(options) {
    Writable.call(this, options);
} // 構(gòu)造函數(shù)
util.inherits(MyWritable, Writable); // 繼承自Writable
MyWritable.prototype._write = function(chunk, encoding, callback) {
    console.log("被寫入的數(shù)據(jù)是:", chunk.toString()); // 此處可對寫入的數(shù)據(jù)進行處理
    callback();
};

process.stdin.pipe(new MyWritable()); // stdin作為輸入源,MyWritable作為輸出源   

文件系統(tǒng)

  • 1. 內(nèi)置的fs模塊架構(gòu)是什么樣子的?

參考答案: fs模塊主要由下面幾部分組成: 1) POSIX文件Wrapper,對應(yīng)于操作系統(tǒng)的原生文件操作 2) 文件流 fs.createReadStream和fs.createWriteStream 3) 同步文件讀寫,fs.readFileSync和fs.writeFileSync 4) 異步文件讀寫, fs.readFile和fs.writeFile

  • 2. 讀寫一個文件有多少種方法?

參考答案: 總體來說有四種: 1) POSIX式低層讀寫 2) 流式讀寫 3) 同步文件讀寫 4) 異步文件讀寫

  • 3. 怎么讀取json配置文件?

參考答案: 主要有兩種方式,第一種是利用node內(nèi)置的require('data.json')機制,直接得到j(luò)s對象; 第二種是讀入文件入內(nèi)容,然后用JSON.parse(content)轉(zhuǎn)換成js對象.二者的區(qū)別是require機制情況下,如果多個模塊都加載了同一個json文件,那么其中一個改變了js對象,其它跟著改變,這是由node模塊的緩存機制造成的,只有一個js模塊對象; 第二種方式則可以隨意改變加載后的js變量,而且各模塊互不影響,因為他們都是獨立的,是多個js對象.

  • 4. fs.watch和fs.watchFile有什么區(qū)別,怎么應(yīng)用?

參考答案: 二者主要用來監(jiān)聽文件變動.fs.watch利用操作系統(tǒng)原生機制來監(jiān)聽,可能不適用網(wǎng)絡(luò)文件系統(tǒng); fs.watchFile則是定期檢查文件狀態(tài)變更,適用于網(wǎng)絡(luò)文件系統(tǒng),但是相比fs.watch有些慢,因為不是實時機制.

網(wǎng)絡(luò)

  • 1. node的網(wǎng)絡(luò)模塊架構(gòu)是什么樣子的?

參考答案: node全面支持各種網(wǎng)絡(luò)服務(wù)器和客戶端,包括tcp, http/https, tcp, udp, dns, tls/ssl等.

  • 2. node是怎樣支持https,tls的?

參考答案: 主要實現(xiàn)以下幾個步驟即可: 1) openssl生成公鑰私鑰 2) 服務(wù)器或客戶端使用https替代http 3) 服務(wù)器或客戶端加載公鑰私鑰證書

  • 3. 實現(xiàn)一個簡單的http服務(wù)器?

參考答案: 經(jīng)典又很沒毛意義的一個題目.思路是加載http模塊,創(chuàng)建服務(wù)器,監(jiān)聽端口.

代碼演示

    var http = require('http'); // 加載http模塊

    http.createServer(function(req, res) {
        res.writeHead(200, {'Content-Type': 'text/html'}); // 200代表狀態(tài)成功, 文檔類型是給瀏覽器識別用的
        res.write('<meta charset="UTF-8"> <h1>我是標題?。?lt;/h1> <font color="red">這么原生,初級的服務(wù)器,下輩子能用著嗎?!</font>'); // 返回給客戶端的html數(shù)據(jù)
        res.end(); // 結(jié)束輸出流
    }).listen(3000); // 綁定3ooo, 查看效果請訪問 http://localhost:3000 

child-process

  • 1. 為什么需要child-process?

參考答案: node是異步非阻塞的,這對高并發(fā)非常有效.可是我們還有其它一些常用需求,比如和操作系統(tǒng)shell命令交互,調(diào)用可執(zhí)行文件,創(chuàng)建子進程進行阻塞式訪問或高CPU計算等,child-process就是為滿足這些需求而生的.child-process顧名思義,就是把node阻塞的工作交給子進程去做.

  • 2. exec,execFile,spawn和fork都是做什么用的?

參考答案: exec可以用操作系統(tǒng)原生的方式執(zhí)行各種命令,如管道 cat ab.txt | grep hello; execFile是執(zhí)行一個文件; spawn是流式和操作系統(tǒng)進行交互; fork是兩個node程序(javascript)之間時行交互.

  • 3. 實現(xiàn)一個簡單的命令行交互程序?

參考答案: 那就用spawn吧.

代碼演示

    var cp = require('child_process');

    var child = cp.spawn('echo', ['你好', "鉤子"]); // 執(zhí)行命令
    child.stdout.pipe(process.stdout); // child.stdout是輸入流,process.stdout是輸出流
    // 這句的意思是將子進程的輸出作為當前程序的輸入流,然后重定向到當前程序的標準輸出,即控制臺
  • 4. 兩個node程序之間怎樣交互?

參考答案: 用fork嘛,上面講過了.原理是子程序用process.on, process.send,父程序里用child.on,child.send進行交互.
代碼演示

    1) fork-parent.js
    var cp = require('child_process');
    var child = cp.fork('./fork-child.js');
    child.on('message', function(msg){
        console.log('老爸從兒子接受到數(shù)據(jù):', msg);
    });
    child.send('我是你爸爸,送關(guān)懷來了!');

    2) fork-child.js
    process.on('message', function(msg){
        console.log("兒子從老爸接收到的數(shù)據(jù):", msg);
        process.send("我不要關(guān)懷,我要銀民幣!");
    });
  • 5. 怎樣讓一個js文件變得像linux命令一樣可執(zhí)行?

參考答案: 1) 在myCommand.js文件頭部加入 #!/usr/bin/env node 2) chmod命令把js文件改為可執(zhí)行即可 3) 進入文件目錄,命令行輸入myComand就是相當于node myComand.js了

  • 6. child-process和process的stdin,stdout,stderror是一樣的嗎?

參考答案: 概念都是一樣的,輸入,輸出,錯誤,都是流.區(qū)別是在父程序眼里,子程序的stdout是輸入流,stdin是輸出流.

node高級話題(異步,部署,性能調(diào)優(yōu),異常調(diào)試等)

  • 1. node中的異步和同步怎么理解

參考答案: node是單線程的,異步是通過一次次的循環(huán)事件隊列來實現(xiàn)的.同步則是說阻塞式的IO,這在高并發(fā)環(huán)境會是一個很大的性能問題,所以同步一般只在基礎(chǔ)框架的啟動時使用,用來加載配置文件,初始化程序什么的.

  • 2. 有哪些方法可以進行異步流程的控制?

參考答案: 1) 多層嵌套回調(diào) 2) 為每一個回調(diào)寫單獨的函數(shù),函數(shù)里邊再回調(diào) 3) 用第三方框架比方async, q, promise等

  • 3. 怎樣綁定node程序到80端口?

參考答案: 多種方式 1) sudo 2) apache/nginx代理 3) 用操作系統(tǒng)的firewall iptables進行端口重定向

  • 4. 有哪些方法可以讓node程序遇到錯誤后自動重啟?

參考答案: 1) runit 2) forever 3) nohup npm start &

  • 5. 怎樣充分利用多個CPU?

參考答案: 一個CPU運行一個node實例

  • 6. 怎樣調(diào)節(jié)node執(zhí)行單元的內(nèi)存大小?

參考答案: 用--max-old-space-size 和 --max-new-space-size 來設(shè)置 v8 使用內(nèi)存的上限

  • 7. 程序總是崩潰,怎樣找出問題在哪里?

參考答案: 1) node --prof 查看哪些函數(shù)調(diào)用次數(shù)多 2) memwatch和heapdump獲得內(nèi)存快照進行對比,查找內(nèi)存溢出

  • 8. 有哪些常用方法可以防止程序崩潰?

參考答案: 1) try-catch-finally 2) EventEmitter/Stream error事件處理 3) domain統(tǒng)一控制 4) jshint靜態(tài)檢查 5) jasmine/mocha進行單元測試

  • 9. 怎樣調(diào)試node程序?

參考答案: node --debug app.js 和node-inspector

常用知名第三方類庫(Async, Express等)

  • 1. async都有哪些常用方法,分別是怎么用?

參考答案: async是一個js類庫,它的目的是解決js中異常流程難以控制的問題.a(chǎn)sync不僅適用在node.js里,瀏覽器中也可以使用. 1) async.parallel并行執(zhí)行完多個函數(shù)后,調(diào)用結(jié)束函數(shù)

    async.parallel([
        function(){ ... },
        function(){ ... }
    ], callback);
  1. async.series串行執(zhí)行完多個函數(shù)后,調(diào)用結(jié)束函數(shù)
    async.series([
        function(){ ... },
        function(){ ... }
    ]);
  1. async.waterfall依次執(zhí)行多個函數(shù),后一個函數(shù)以前面函數(shù)的結(jié)果作為輸入?yún)?shù)
    async.waterfall([
        function(callback) {
            callback(null, 'one', 'two');
        },
        function(arg1, arg2, callback) {
          // arg1 now equals 'one' and arg2 now equals 'two' 
            callback(null, 'three');
        },
        function(arg1, callback) {
            // arg1 now equals 'three' 
            callback(null, 'done');
        }
    ], function (err, result) {
        // result now equals 'done' 
    });
  1. async.map異步執(zhí)行多個數(shù)組,返回結(jié)果數(shù)組
    async.map(['file1','file2','file3'], fs.stat, function(err, results){
        // results is now an array of stats for each file 
    });
  1. async.filter異步過濾多個數(shù)組,返回結(jié)果數(shù)組
    async.filter(['file1','file2','file3'], fs.exists, function(results){
        // results now equals an array of the existing files 
    });
  • 2. express項目的目錄大致是什么樣子的

參考答案: app.js, package.json, bin/www, public, routes, views.

  • 3. express常用函數(shù)

參考答案: express.Router路由組件,app.get路由定向,app.configure配置,app.set設(shè)定參數(shù),app.use使用中間件

  • 4. express中如何獲取路由的參數(shù)

參考答案: /users/:name使用req.params.name來獲取; req.body.username則是獲得表單傳入?yún)?shù)username; express路由支持常用通配符 ?, +, *, and ()

  • 5. express response有哪些常用方法

參考答案: res.download() 彈出文件下載
res.end() 結(jié)束response
res.json() 返回json
res.jsonp() 返回jsonp
res.redirect() 重定向請求
res.render() 渲染模板
res.send() 返回多種形式數(shù)據(jù)
res.sendFile 返回文件
res.sendStatus() 返回狀態(tài)

其它相關(guān)后端常用技術(shù)(MongoDB, Redis, Apache, Nginx等)

  • 1. mongodb有哪些常用優(yōu)化措施

參考答案: 類似傳統(tǒng)數(shù)據(jù)庫,索引和分區(qū).

  • 2. redis支持哪些功能

參考答案: set/get, hset/hget, publish/subscribe, expire

  • 3. redis最簡單的應(yīng)用

參考答案:

    var redis = require("redis"),
        client = redis.createClient();

    client.set("foo_rand000000000000", "some fantastic value");
    client.get("foo_rand000000000000", function (err, reply) {
        console.log(reply.toString());
    });
    client.end();
  • 4. apache,nginx有什么區(qū)別?

參考答案: 二者都是代理服務(wù)器,功能類似.a(chǎn)pache應(yīng)用簡單,相當廣泛.nginx在分布式,靜態(tài)轉(zhuǎn)發(fā)方面比較有優(yōu)勢.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文鏈接:https://github.com/jimuyouyou/node-interview-questio...
    R_X閱讀 9,598評論 0 26
  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測試 ...
    KeKeMars閱讀 6,610評論 0 6
  • # 模塊機制 node采用模塊化結(jié)構(gòu),按照CommonJS規(guī)范定義和使用模塊,模塊與文件是一一對應(yīng)關(guān)系,即加載一個...
    RichRand閱讀 2,736評論 0 3
  • 內(nèi)容來自《Node.js開發(fā)指南》 核心模塊是 Node.js 的心臟,它由一些精簡而高效的庫組成,為 Node....
    angelwgh閱讀 980評論 0 1
  • 今天星期六,今天可不是普通的星期六,今天早上5點多,我就肚子疼,閨女早早的扶我起來,和我一起去醫(yī)院,迎接三...
    夏雯敏閱讀 222評論 0 0

友情鏈接更多精彩內(nèi)容