最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js domain模塊處理錯(cuò)誤的問題操作

 更新時(shí)間:2026年04月07日 09:29:03   作者:吳聲子夜歌  
文章主要介紹了Node.js中的domain模塊,用于處理未被處理的錯(cuò)誤,它提供了Domain對象,可以捕獲任何未被處理的錯(cuò)誤,并允許用戶通過創(chuàng)建、綁定、攔截回調(diào)函數(shù)及彈出與推入domain堆棧等操作來控制錯(cuò)誤處理,感興趣的朋友跟隨小編一起看看吧

1、domain模塊概述

眾所周知,在JavaScript腳本代碼中,雖然可以使用try…catch機(jī)制來捕捉同步方法中拋出的錯(cuò)誤,但是不能使用try…catch機(jī)制來捕捉異步方法中拋出的錯(cuò)誤。

例如,由于在下面這段代碼中使用了同步模式的readFileSync方法讀取文件,因此可以使用try…catch機(jī)制來捕捉在執(zhí)行該方法時(shí)拋出的錯(cuò)誤。

varfs=require('fs');
try{
var data=fs.readFileSync('test.txt','utf8');
    //在控制臺中輸出文件內(nèi)容
    console.log(data);
}
catch(ex){
    console.log('讀取文件時(shí)發(fā)生錯(cuò)誤。');
}

現(xiàn)在查看如下所示的代碼。在這段代碼中,創(chuàng)建了一個(gè)HTTP服務(wù)器,該服務(wù)器在接收到客戶端請求后,向客戶端返回“你好”字符串。在用于創(chuàng)建HTTP服務(wù)器的createServer方法所使用的callback參數(shù)值回調(diào)函數(shù)中,將首先調(diào)用一個(gè)并不存在的方法noneexist,這必然會(huì)導(dǎo)致回調(diào)函數(shù)中拋出一個(gè)錯(cuò)誤,假如我們采用try…catch機(jī)制,將捕捉不到該錯(cuò)誤。

var http = require('http');
try{
    http.createServer(function (req, res) {
        if(req.url!=="/favicon.ico"){
            noneexist();
            res.writeHead(200, {'Content-Type': 'text/html'});
            res.write('<head><meta charset="utf-8"/></head>');
            res.end('你好\n');
        }
    }).listen(1337, "127.0.0.1");
}
catch(err){
    console.log('接收客戶端請求時(shí)發(fā)生以下錯(cuò)誤:');
    console.log(err.code);
}

將這段代碼保存在應(yīng)用程序根目錄下的app.js文件中,然后在命令行窗口中運(yùn)行該文件,接著在瀏覽器的地址欄中輸入“http://localhost:1337”?,此時(shí),命令行窗口中將顯示一個(gè)錯(cuò)誤被觸發(fā),應(yīng)用程序也將由于該錯(cuò)誤的觸發(fā)而導(dǎo)致關(guān)閉。

修改上述代碼,在該示例代碼中,改為使用uncaughtException事件來捕獲任何未被處理的錯(cuò)誤。

var http = require('http');
http.createServer(function (req, res) {
    if(req.url!=="/favicon.ico"){
        noneexist();
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write('<head><meta charset="utf-8"/></head>');
        res.end('你好\n');
    }
}).listen(1337, "127.0.0.1");
process.on('uncaughtException', function(err) {
    console.log('接收客戶端請求時(shí)發(fā)生以下錯(cuò)誤:');
    console.log(err);
});

瀏覽器的地址欄中輸入“http://localhost:1337”?,命令行窗口中將顯示被觸發(fā)的錯(cuò)誤。雖然該錯(cuò)誤被觸發(fā),但是應(yīng)用程序不會(huì)被強(qiáng)制關(guān)閉,如圖所示。

雖然使用uncaughtException事件可以捕捉任何未被處理的錯(cuò)誤,但這是一種“粗魯”的處理方法,有可能產(chǎn)生資源泄漏、內(nèi)存泄漏等一系列非常惡劣的影響。例如,在本例中,客戶端將永遠(yuǎn)得不到服務(wù)器端的響應(yīng)。

為了解決這一問題,從Node.js v0.8版開始,提供domain模塊。該模塊中提供一個(gè)Domain對象,當(dāng)應(yīng)用程序在任何時(shí)刻拋出錯(cuò)誤時(shí)可以通知該對象,然后由該對象來統(tǒng)一處理這些錯(cuò)誤。

使用domain模塊來處理未被處理的錯(cuò)誤:

var http = require('http');
var domain = require('domain');
http.createServer(function (req, res) {
    var d = domain.create();
    d.once('error', function(err) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write('<head><meta charset="utf-8"/></head>');
        res.write('服務(wù)器端接收客戶端請求時(shí)發(fā)生以下錯(cuò)誤:');
        res.end(err.message);
    });
    d.run(function() {
        if(req.url!=="/favicon.ico"){
            noneexist();
            res.writeHead(200, {'Content-Type': 'text/html'});
            res.write('<head><meta charset="utf-8"/></head>');
            res.end('你好\n');
        }
    });
}).listen(1337, "127.0.0.1");

命令行窗口中運(yùn)行該文件,接著在瀏覽器的地址欄中輸入http://localhost:1337,雖然服務(wù)器端觸發(fā)一個(gè)錯(cuò)誤,但是客戶端可以接收到錯(cuò)誤信息,如圖所示。

2、創(chuàng)建并使用Domain對象

首先需要使用domain模塊中的create方法創(chuàng)建一個(gè)Domain對象,該方法的使用方式如下:

let domain = domain.create();

create方法沒有任何參數(shù),該方法返回被創(chuàng)建的Domain對象。該對象是一個(gè)繼承了EventEmitter類的實(shí)例對象,當(dāng)該對象捕獲到任何錯(cuò)誤時(shí),觸發(fā)該對象的error事件??梢酝ㄟ^監(jiān)聽該對象的error事件并指定事件回調(diào)函數(shù)的方法來實(shí)現(xiàn)當(dāng)捕捉到錯(cuò)誤時(shí)的處理。該回調(diào)函數(shù)的指定方法如下所示(代碼中的domain代表一個(gè)Domain對象)?。

domain.on('error', function(err) {
    //事件回調(diào)函數(shù)代碼略
});

在Domain對象的error事件回調(diào)函數(shù)中,使用一個(gè)參數(shù),其參數(shù)值為被觸發(fā)的錯(cuò)誤對象。

在domain模塊中,為Domain對象定義一個(gè)name屬性值,可以使用該屬性值來設(shè)置或獲取該Domain對象的名稱。

在Domain對象被創(chuàng)建后,需要指定該對象所監(jiān)聽的代碼,我們需要將這些代碼書寫在一個(gè)函數(shù)中,并且使用Domain對象的run方法指定Domain對象監(jiān)聽該函數(shù)中的代碼。當(dāng)這些代碼觸發(fā)任何錯(cuò)誤時(shí),將被Domain對象捕獲。Domain對象的run方法的指定方法如下所示(代碼中的domain代表一個(gè)Domain對象)?。

domain.run(fn)

在Domain對象的run方法中,使用一個(gè)參數(shù),參數(shù)值為一個(gè)函數(shù)。當(dāng)該函數(shù)中觸發(fā)任何錯(cuò)誤時(shí),將被Domain對象捕獲。

let domain = require('domain');
let rfs = require('fs');
let d = domain.create();
d.name='d1';
d.on('error', (err)=>{
    console.error('%s捕獲到錯(cuò)誤!',d.name,err);
});
d.run(()=>{
    process.nextTick(()=>{
        setTimeout(()=>{ //模擬一個(gè)回調(diào)函數(shù)
            rfs.open('non-existent file', 'r', (err, fd)=>{
                if (err) 
                    throw err;
            });
        }, 1000);
    });
});
d1捕獲到錯(cuò)誤! [Error: ENOENT: no such file or directory, open 'non-existent file'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'non-existent file',
  domainThrown: true
}

3、隱式綁定與顯示綁定

3.1、隱式綁定

當(dāng)使用Domain對象的run方法指定Domain對象所要監(jiān)聽的函數(shù)時(shí),函數(shù)中使用的所有繼承了EventEmitter類的實(shí)例對象(包括各種用于讀取或?qū)懭肓鲾?shù)據(jù)的對象,以及客戶端請求對象、服務(wù)器端響應(yīng)對象等各種有可能觸發(fā)事件的對象)都隱式地綁定到Domain對象上,如果這些對象觸發(fā)錯(cuò)誤,這些錯(cuò)誤都將被Domain對象捕獲。

有時(shí),我們可能不想讓代碼中的某些對象所觸發(fā)的錯(cuò)誤被Domain對象捕獲,或者想讓這些錯(cuò)誤被其他的Domain對象捕獲。在這些場合下,應(yīng)該將這些對象顯式地綁定到Domain對象上。例如,我們有時(shí)可能想為HTTP服務(wù)器綁定一個(gè)Domain對象,而為每個(gè)客戶端請求單獨(dú)綁定一個(gè)Domain對象。

3.2、顯示綁定

在實(shí)現(xiàn)顯式綁定時(shí),需要使用Domain對象的add方法,該方法的使用方式如下所示(代碼中的domain代表一個(gè)Domain對象)?。

domain.add(emitter)

在Domain對象的add方法中,使用一個(gè)參數(shù),其參數(shù)值可以為一個(gè)需要被綁定的繼承了EventEmitter類的實(shí)例對象。如果該實(shí)例對象觸發(fā)了一個(gè)錯(cuò)誤,該錯(cuò)誤將被Domain對象所捕獲并觸發(fā)Domain對象的error事件。add方法的參數(shù)值也可以為一個(gè)通過setInterval方法或setTimeout方法返回的定時(shí)器。如果該定時(shí)器所執(zhí)行的回調(diào)函數(shù)中拋出一個(gè)錯(cuò)誤,那么該錯(cuò)誤也將被Domain對象所捕獲并觸發(fā)Domain對象的error事件。

顯示綁定domain示例:

在該示例代碼中,我們創(chuàng)建一個(gè)HTTP服務(wù)器,并指定當(dāng)服務(wù)器接收到客戶端請求時(shí),首先創(chuàng)建一個(gè)Domain對象,然后使用該對象的add方法分別將用于讀取客戶端請求數(shù)據(jù)的http.IncomingMessage對象與用于發(fā)送服務(wù)器端響應(yīng)數(shù)據(jù)的http.ServerResponse對象綁定到Domain對象上,并指定當(dāng)Domain對象捕獲到錯(cuò)誤時(shí)向客戶端返回“服務(wù)器端接收客戶端請求時(shí)發(fā)生以下錯(cuò)誤:?”字符串與被觸發(fā)的錯(cuò)誤消息。在http.IncomingMessage對象接收到客戶端發(fā)送數(shù)據(jù)而觸發(fā)的data事件回調(diào)函數(shù)中,首先使用一個(gè)不存在的方法noneexists,然后向客戶端返回“你好。?”字符串。

const http = require('http');
const domain = require('domain');
http.createServer((req, res)=>{
    let reqd = domain.create();
    //綁定對象
    reqd.add(req);
    reqd.add(res);
    reqd.on('error', (err)=>{
        res.writeHead(200);
        res.write('服務(wù)器端接收客戶端請求時(shí)發(fā)生以下錯(cuò)誤:');
        res.end(err.message);
    });
    res.writeHead(200);
    req.on('data',()=>{
        noneexists();
        res.write('你好。');
        res.end();
    });
}).listen(1337);

接下來創(chuàng)建一個(gè)向HTTP服務(wù)器提交請求并發(fā)送數(shù)據(jù)的模塊文件,代碼如代碼清單10-6所示。在該示例代碼中,我們向在代碼清單10-5所示示例中創(chuàng)建的HTTP服務(wù)器提交請求,指定當(dāng)客戶端接收到服務(wù)器端返回?cái)?shù)據(jù)時(shí)在控制臺中輸出這些數(shù)據(jù),并向HTTP服務(wù)器發(fā)送“你好。?”字符串與“再見。?”字符串。

const http = require('http');
let options = {
    hostname: 'localhost',
    port: 1337,
    path: '/',
    method: 'POST'
};
let req = http.request(options,(res)=>{
    res.setEncoding('utf8');
    res.on('data', (chunk)=>{
        console.log('響應(yīng)內(nèi)容: '+chunk);
    });
});
req.write('你好。');
req.end('再見。');

一個(gè)命令行窗口中運(yùn)行server.js文件,在另一個(gè)命令行窗口中運(yùn)行client.js文件,該命令行窗口中顯示的結(jié)果如下:

3.3、取消顯示綁定

在使用了Domain對象的add方法繼承了EventEmitter類的實(shí)例對象與該Domain對象進(jìn)行綁定后,可以使用Domain對象的remove方法取消這些對象的綁定,該方法的使用方式如下所示。

domain.remove(emitter)

在Domain對象的remove方法中,使用一個(gè)參數(shù),其參數(shù)值為一個(gè)需要被解除綁定的繼承了EventEmitter類的實(shí)例對象。在解除綁定后,如果該實(shí)例對象觸發(fā)了一個(gè)錯(cuò)誤,該錯(cuò)誤將不再被Domain對象所捕獲。

修改createServer方法所使用的callback參數(shù)值回調(diào)函數(shù)代碼,在使用了Domain對象的add方法之后,使用Domain對象的remove方法解除http.IncomingMessage對象與Domain對象的綁定,修改后的代碼如下所示。

const http = require('http');
const domain = require('domain');
http.createServer((req, res)=>{
    let reqd = domain.create();
    //綁定對象
    reqd.add(req);
    reqd.add(res);
    reqd.on('error', (err)=>{
        res.writeHead(200);
        res.write('服務(wù)器端接收客戶端請求時(shí)發(fā)生以下錯(cuò)誤:');
        res.end(err.message);
    });
    res.writeHead(200);
    //取消綁定
    reqd.remove(req);
    req.on('data',()=>{
        noneexists();
        res.write('你好。');
        res.end();
    });
}).listen(1337);

然后在一個(gè)命令行窗口中運(yùn)行server.js文件,在另一個(gè)命令行窗口中運(yùn)行client.js文件,在用于運(yùn)行server.js文件的窗口中將顯示由于運(yùn)行一個(gè)不存在的方法而導(dǎo)致一個(gè)錯(cuò)誤被觸發(fā),如圖所示。

4、綁定回調(diào)函數(shù)與攔截回調(diào)函數(shù)

4.1、綁定回調(diào)函數(shù)

可以使用Domain對象的bind方法將一個(gè)回調(diào)函數(shù)與該Domain對象進(jìn)行綁定,該方法的使用方式如下所示。

domain.bind(callback)

在Domain對象的bind方法中,使用一個(gè)參數(shù),其參數(shù)值為一個(gè)回調(diào)函數(shù),用于指定需要被綁定的回調(diào)函數(shù)。bind方法返回一個(gè)函數(shù),該函數(shù)將代替原回調(diào)函數(shù)被調(diào)用。當(dāng)該函數(shù)被調(diào)用時(shí),將內(nèi)部調(diào)用bind方法的參數(shù)值回調(diào)函數(shù),當(dāng)該回調(diào)函數(shù)中拋出任何錯(cuò)誤時(shí),Domain對象將捕獲這些錯(cuò)誤,在Domain對象的error事件回調(diào)函數(shù)中的參數(shù)值為該錯(cuò)誤對象。

查看一個(gè)bind方法的使用示例,代碼如代碼清單10-7所示。在該示例代碼中,我們首先創(chuàng)建一個(gè)Domain對象,然后使用fs模塊中的readFile方法讀取一個(gè)并不存在的文件,并使用Domain對象的bind方法將讀取文件操作結(jié)束時(shí)執(zhí)行的回調(diào)函數(shù)與Domain對象綁定到一起。在回調(diào)函數(shù)中,我們指定,當(dāng)讀取文件操作發(fā)生錯(cuò)誤時(shí),將該錯(cuò)誤拋出。在Domain對象的error事件回調(diào)函數(shù)中,我們指定,當(dāng)捕獲到錯(cuò)誤時(shí),在控制臺中輸出該錯(cuò)誤。

const fs=require('fs');
const domain = require('domain');
let d = domain.create();
fs.readFile('./test.txt', d.bind(function(err, data) {
     if(err) 
          throw err;
     else 
          console.log(data);
}));
d.on('error', (err)=>{
    console.log('讀取文件時(shí)發(fā)生以下錯(cuò)誤:');
    console.log(err);
});

4.2、攔截回調(diào)函數(shù)

可以使用Domain對象的intercept方法攔截一個(gè)回調(diào)函數(shù)中觸發(fā)的錯(cuò)誤。該方法的作用及其使用方法與Domain對象的bind方法有些相似,都是捕獲一個(gè)回調(diào)函數(shù)中所觸發(fā)的錯(cuò)誤,它們的區(qū)別在于,在使用bind方法時(shí),回調(diào)函數(shù)中必須使用throw關(guān)鍵字拋出該錯(cuò)誤,而在使用intercept方法時(shí),回調(diào)函數(shù)不需要再拋出該錯(cuò)誤,該錯(cuò)誤將直接被Domain對象攔截。

intercept方法的使用方式如下所示。

domain.intercept(callback)

在Domain對象的intercept方法中,使用一個(gè)參數(shù),其參數(shù)值為一個(gè)回調(diào)函數(shù),用于指定需要被攔截的回調(diào)函數(shù)。intercept方法返回一個(gè)函數(shù),該函數(shù)將代替原回調(diào)函數(shù)被調(diào)用。當(dāng)該函數(shù)被調(diào)用時(shí),將內(nèi)部調(diào)用bind方法的參數(shù)值回調(diào)函數(shù),當(dāng)該回調(diào)函數(shù)中拋出任何錯(cuò)誤時(shí),將被Domain對象所捕獲,在Domain對象的error事件回調(diào)函數(shù)中的參數(shù)值為該錯(cuò)誤對象。

const fs=require('fs');
const domain = require('domain');
let d = domain.create();
fs.readFile('./test.txt', d.intercept(function(err, data) {
    console.log(data);
}));
d.on('error', (err)=>{
    console.log('讀取文件時(shí)發(fā)生以下錯(cuò)誤:');
    console.log(err);
});

5、domain堆棧的彈出與推入

在Node.js中,當(dāng)使用Domain對象的run方法、bind方法與intercept方法指定Domain對象所需監(jiān)聽的函數(shù)時(shí),將把該Domain對象推入到domain模塊所維護(hù)的一個(gè)domain堆棧中。可以通過domain中的_stack屬性值來查看domain堆棧中的內(nèi)容。

5.1、推入

在該示例代碼中,分別創(chuàng)建兩個(gè)Domain對象并分別將其命名為d1與d2,然后輸出domain堆棧中的原始內(nèi)容。接著,使用d1對象的run方法指定其所監(jiān)聽的函數(shù),并在該函數(shù)代碼中指定在控制臺中輸出運(yùn)行了d1對象的run方法后堆棧中的內(nèi)容,然后使用d2對象的run方法指定其所監(jiān)聽的函數(shù),并在該函數(shù)代碼中指定在控制臺中輸出運(yùn)行了d2對象的run方法后堆棧中的內(nèi)容。

const domain = require('domain');
let d1 = domain.create();
d1.name="d1";
let d2 = domain.create();
d2.name = "d2";
console.log('原始堆棧:');
console.log(domain._stack);
d1.run(()=>{
    console.log('d1對象:');
    console.log(d1);
    console.log('運(yùn)行d1對象后的堆棧內(nèi)容:');
    console.log(domain._stack);
});
d2.run(()=>{
    console.log('d2對象:');
    console.log(d2);
    console.log('運(yùn)行d2對象后的堆棧內(nèi)容:');
    console.log(domain._stack);
});
運(yùn)行d1對象后的堆棧內(nèi)容:
[
  Domain {
    _events: [Object: null prototype] {
      removeListener: [Function: updateExceptionCapture],
      newListener: [Function: updateExceptionCapture]
    },
    _eventsCount: 2,
    _maxListeners: undefined,
    members: [],
    name: 'd1',
    [Symbol(kCapture)]: false,
    [Symbol(kWeak)]: WeakReference {}
  }
]
d2對象:
Domain {
  _events: [Object: null prototype] {
    removeListener: [Function: updateExceptionCapture],
    newListener: [Function: updateExceptionCapture]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  members: [],
  name: 'd2',
  [Symbol(kCapture)]: false,
  [Symbol(kWeak)]: WeakReference {}
}
運(yùn)行d2對象后的堆棧內(nèi)容:
[
  Domain {
    _events: [Object: null prototype] {
      removeListener: [Function: updateExceptionCapture],
      newListener: [Function: updateExceptionCapture]
    },
    _eventsCount: 2,
    _maxListeners: undefined,
    members: [],
    name: 'd2',
    [Symbol(kCapture)]: false,
    [Symbol(kWeak)]: WeakReference {}
  }
]

從這個(gè)結(jié)果中可以看出,在未運(yùn)行任何Domain對象的run方法、bind方法與intercept方法時(shí),domain堆棧中的內(nèi)容為空,而在運(yùn)行一個(gè)Domain對象的run方法、bind方法與intercept方法之后,該Domain對象被推入domain堆棧,另外,在運(yùn)行另一個(gè)與堆棧中當(dāng)前Domain對象并級的Domain對象的run方法、bind方法與intercept方法之后,另外,堆棧中當(dāng)前Domain對象被彈出堆棧,后一個(gè)Domain對象被推入domain堆棧。

5.2、彈出

可以使用Domain對象的exit方法將該Domain對象從domain堆棧中彈出。該Domain對象從domain堆棧中彈出后將不能再捕獲任何錯(cuò)誤。

首先創(chuàng)建了一個(gè)Domain對象,并指定該Domain對象的error事件函數(shù),在該函數(shù)代碼中指定當(dāng)Domain對象捕獲到錯(cuò)誤時(shí)在控制臺中輸出“Domain對象捕獲到錯(cuò)誤。?”字符串。然后,輸出domain堆棧中的原始內(nèi)容。接下來,使用Domain對象的run方法指定其所監(jiān)聽的函數(shù),在該函數(shù)代碼中指定在控制臺中輸出運(yùn)行了Domain對象的run方法后堆棧中的內(nèi)容,最后拋出一個(gè)自定義錯(cuò)誤。

const domain = require('domain');
let d = domain.create();
d.on('error',(err)=>{
    console.log('Domain對象捕獲到錯(cuò)誤。');
});
console.log('原始堆棧:');
console.log(domain._stack);
d.run(()=>{
    console.log('運(yùn)行domain對象后的堆棧內(nèi)容:');
    console.log(domain._stack);
    throw new Error("error");
});
運(yùn)行domain對象后的堆棧內(nèi)容:
[
  Domain {
    _events: [Object: null prototype] {
      removeListener: [Function: updateExceptionCapture],
      newListener: [Function: updateExceptionCapture],
      error: [Function (anonymous)]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    members: [],
    [Symbol(kCapture)]: false,
    [Symbol(kWeak)]: WeakReference {}
  }
]
Domain對象捕獲到錯(cuò)誤。

在Domain對象的run方法所指定監(jiān)聽的函數(shù)中,添加使用Domain對象的exit方法,并且暫時(shí)注釋掉函數(shù)中用于拋出自定義錯(cuò)誤的代碼,修改后的代碼如下所示。

const domain = require('domain');
let d = domain.create();
d.on('error',(err)=>{
    console.log('Domain對象捕獲到錯(cuò)誤。');
});
console.log('原始堆棧:');
console.log(domain._stack);
d.run(()=>{
     //出棧
     d.exit();
    console.log('運(yùn)行domain對象后的堆棧內(nèi)容:');
    console.log(domain._stack);
    throw new Error("error");
});
原始堆棧:
[]
運(yùn)行domain對象后的堆棧內(nèi)容:
[]
/Users/acton_zhang/前端/vscodeworkspace/node/demo/index.js:13
    throw new Error("error");
    ^
Error: error
    at Domain.<anonymous> (/Users/acton_zhang/前端/vscodeworkspace/node/demo/index.js:13:11)
    at Domain.run (domain.js:373:14)
    at Object.<anonymous> (/Users/acton_zhang/前端/vscodeworkspace/node/demo/index.js:8:3)
    at Module._compile (internal/modules/cjs/loader.js:1118:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1138:10)
    at Module.load (internal/modules/cjs/loader.js:982:32)
    at Function.Module._load (internal/modules/cjs/loader.js:875:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47

在使用了Domain對象的exit方法后,該對象將不能再捕獲任何錯(cuò)誤。

可以使用Domain對象的enter方法將一個(gè)Domain對象推入domain堆棧中并使該Domain對象變?yōu)楫?dāng)前使用的Domain對象。

在Domain對象的run方法所指定監(jiān)聽的函數(shù)中,在使用了Domain對象的exit方法之后,使用該對象的enter方法再將它推入domain堆棧,并且在控制臺中顯示使用Domain對象的enter方法后domain堆棧中的內(nèi)容。修改后的代碼如下所示。

const domain = require('domain');
let d = domain.create();
d.on('error',(err)=>{
    console.log('Domain對象捕獲到錯(cuò)誤。');
});
console.log('原始堆棧:');
console.log(domain._stack);
d.run(()=>{
     //出棧
     d.exit();
     console.log('運(yùn)行exit方法后的堆棧內(nèi)容:');
     console.log(domain._stack);
     //入棧
     d.enter();
     console.log('運(yùn)行enter方法后的堆棧內(nèi)容:');
     console.log(domain._stack);
     throw new Error("error");
});
運(yùn)行enter方法后的堆棧內(nèi)容:
[
  Domain {
    _events: [Object: null prototype] {
      removeListener: [Function: updateExceptionCapture],
      newListener: [Function: updateExceptionCapture],
      error: [Function (anonymous)]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    members: [],
    [Symbol(kCapture)]: false,
    [Symbol(kWeak)]: WeakReference {}
  }
]
Domain對象捕獲到錯(cuò)誤。

如果在一個(gè)Domain對象所監(jiān)聽的函數(shù)中使用另一個(gè)Domain對象的enter方法,另一個(gè)Domain對象將被推入到domain堆棧中,然后改為使用該Domain對象來捕捉第一個(gè)Domain對象所監(jiān)聽的函數(shù)中拋出的錯(cuò)誤。

接下來看一個(gè)在Domain對象中嵌套使用另一個(gè)Domain對象的示例。在該示例代碼中,創(chuàng)建兩個(gè)Domain對象,并分別將其命名為d1與d2。指定d1對象的error事件函數(shù),在該函數(shù)代碼中指定當(dāng)d1對象捕獲到錯(cuò)誤時(shí)在控制臺中輸出“d1對象捕獲到錯(cuò)誤。?”字符串,指定d2對象的error事件函數(shù),在該函數(shù)代碼中指定當(dāng)d2對象捕獲到錯(cuò)誤時(shí)在控制臺中輸出“d2對象捕獲到錯(cuò)誤。?”字符串。然后,輸出domain堆棧中的原始內(nèi)容。接下來,使用d1對象的run方法指定其所監(jiān)聽的函數(shù),在該函數(shù)代碼中使用d2對象的run方法指定其所監(jiān)聽的函數(shù),在這個(gè)嵌套的函數(shù)代碼中指定在控制臺中輸出在運(yùn)行了d2對象的run方法之后堆棧中的內(nèi)容,并且拋出一個(gè)自定義錯(cuò)誤。

const domain = require('domain');
let d1 = domain.create();
d1.name="d1";
d1.on('error',(err)=>{
    console.log('d1對象捕獲到錯(cuò)誤。');
});
let d2 = domain.create();
d2.name = "d2";
d2.on('error',(err)=>{
    console.log('d2對象捕獲到錯(cuò)誤。');
});
console.log('原始堆棧:');
console.log(domain._stack);
d1.run(()=>{
    d2.run(()=>{
        console.log('最終堆棧:');
        console.log(domain._stack);
        throw new Error("first");
    });
});
原始堆棧:
[]
最終堆棧:
[
  Domain {
    _events: [Object: null prototype] {
      removeListener: [Function: updateExceptionCapture],
      newListener: [Function: updateExceptionCapture],
      error: [Function (anonymous)]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    members: [],
    name: 'd1',
    [Symbol(kCapture)]: false,
    [Symbol(kWeak)]: WeakReference {}
  },
  Domain {
    _events: [Object: null prototype] {
      removeListener: [Function: updateExceptionCapture],
      newListener: [Function: updateExceptionCapture],
      error: [Function (anonymous)]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    members: [],
    name: 'd2',
    [Symbol(kCapture)]: false,
    [Symbol(kWeak)]: WeakReference {}
  }
]
d2對象捕獲到錯(cuò)誤。

如果在d2對象的run方法中使用d1對象的enter方法,將把d1對象推入domain堆棧的最頂層,在使用了d1對象的enter方法之后的代碼中拋出的錯(cuò)誤將被d1對象捕獲,如圖所示。

d1.run(()=>{
     d2.run(()=>{
          //d1進(jìn)入棧頂
          d1.enter();
          console.log('最終堆棧:');
          console.log(domain._stack);
          throw new Error("first");
     });
});
原始堆棧:
[]
最終堆棧:
[
  Domain {
    _events: [Object: null prototype] {
      removeListener: [Function: updateExceptionCapture],
      newListener: [Function: updateExceptionCapture],
      error: [Function (anonymous)]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    members: [],
    name: 'd1',
    [Symbol(kCapture)]: false,
    [Symbol(kWeak)]: WeakReference {}
  },
  Domain {
    _events: [Object: null prototype] {
      removeListener: [Function: updateExceptionCapture],
      newListener: [Function: updateExceptionCapture],
      error: [Function (anonymous)]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    members: [],
    name: 'd2',
    [Symbol(kCapture)]: false,
    [Symbol(kWeak)]: WeakReference {}
  },
  Domain {
    _events: [Object: null prototype] {
      removeListener: [Function: updateExceptionCapture],
      newListener: [Function: updateExceptionCapture],
      error: [Function (anonymous)]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    members: [],
    name: 'd1',
    [Symbol(kCapture)]: false,
    [Symbol(kWeak)]: WeakReference {}
  }
]
d1對象捕獲到錯(cuò)誤。

如果在Domain對象中嵌套使用其他Domain對象,則在最外層的Domain對象的exit方法被調(diào)用后,該對象及其內(nèi)部嵌套的所有Domain對象都被彈出domain堆棧,所有被彈出的Domain對象都不能再捕獲任何錯(cuò)誤。

d1.run(()=>{
     d2.run(()=>{
          //d1出棧
          d1.exit();
          console.log('最終堆棧:');
          console.log(domain._stack);
          // throw new error("first");
     });
});
原始堆棧:
[]
最終堆棧:
[]

在使用了d1對象的exit方法后domain堆棧中的Domain對象全部彈出。

6、domain對象的銷毀

在一個(gè)Domain對象不再需要使用之后,可以使用該對象的dispose方法將其銷毀。在該對象被銷毀后,所有與該對象綁定的對象或回調(diào)函數(shù)都被解除綁定,這些對象或回調(diào)函數(shù)所觸發(fā)的錯(cuò)誤不再被該Domain對象捕獲,在Domain對象的run方法中指定的函數(shù)將不再被運(yùn)行,與Domain對象綁定的定時(shí)器也將不再被運(yùn)行。

d.dispose();

到此這篇關(guān)于Node.js domain模塊處理錯(cuò)誤的問題小結(jié)的文章就介紹到這了,更多相關(guān)Node.js domain模塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • node.js中的fs.fchownSync方法使用說明

    node.js中的fs.fchownSync方法使用說明

    這篇文章主要介紹了node.js中的fs.fchownSync方法使用說明,本文介紹了fs.fchownSync方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • 搭建pomelo 開發(fā)環(huán)境

    搭建pomelo 開發(fā)環(huán)境

    Pomelo是基于 Node.js 的高性能、分布式游戲服務(wù)器框架。它包括基礎(chǔ)的開發(fā)框架和相關(guān)的擴(kuò)展組件(庫和工具包),可以幫助你省去游戲開發(fā)枯燥中的重復(fù)勞動(dòng)和底層邏輯的開發(fā)。Pomelo不但適用于游戲服務(wù)器開發(fā),也可用于開發(fā)高實(shí)時(shí) Web 應(yīng)用
    2014-06-06
  • node 解析圖片二維碼的內(nèi)容代碼實(shí)例

    node 解析圖片二維碼的內(nèi)容代碼實(shí)例

    這篇文章主要介紹了node 解析圖片二維碼的內(nèi)容代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 用npm-run實(shí)現(xiàn)自動(dòng)化任務(wù)的方法示例

    用npm-run實(shí)現(xiàn)自動(dòng)化任務(wù)的方法示例

    這篇文章主要介紹了用npm-run實(shí)現(xiàn)自動(dòng)化任務(wù)的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-01-01
  • NodeJS加密解密及node-rsa加密解密用法詳解

    NodeJS加密解密及node-rsa加密解密用法詳解

    要用nodejs開發(fā)接口,實(shí)現(xiàn)遠(yuǎn)程調(diào)用,如果裸奔太危險(xiǎn)了,就在網(wǎng)上找了一下nodejs的加密,感覺node-rsa挺不錯(cuò)的,下面來總結(jié)一下簡單的rsa加密解密用法,需要的朋友可以參考下
    2018-10-10
  • NodeJs測試框架Mocha的安裝與使用

    NodeJs測試框架Mocha的安裝與使用

    本文全面介紹如何使用Mocha,讓你輕松上手。如果你以前對測試一無所知,本文也可以當(dāng)作JavaScript單元測試入門。
    2017-03-03
  • nodejs nedb 封裝庫與使用方法示例

    nodejs nedb 封裝庫與使用方法示例

    這篇文章主要介紹了nodejs nedb 封裝庫與使用方法,結(jié)合實(shí)例形式分析了nodejs nedb.js封裝庫的定義與使用技巧,需要的朋友可以參考下
    2020-02-02
  • 詳解用node.js實(shí)現(xiàn)簡單的反向代理

    詳解用node.js實(shí)現(xiàn)簡單的反向代理

    本篇文章主要介紹了詳解用node.js實(shí)現(xiàn)簡單的反向代理,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • Node.js基礎(chǔ)入門之path模塊,url模塊,http模塊使用詳解

    Node.js基礎(chǔ)入門之path模塊,url模塊,http模塊使用詳解

    這篇文章主要為大家介紹了Node.js中的三個(gè)模塊(path、url、http)的使用詳解,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-03-03
  • node將對象轉(zhuǎn)化為query的實(shí)現(xiàn)方法

    node將對象轉(zhuǎn)化為query的實(shí)現(xiàn)方法

    本文主要介紹了node將對象轉(zhuǎn)化為query的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01

最新評論

桦甸市| 靖州| 平安县| 兴化市| 乌鲁木齐市| 固阳县| 湘乡市| 建水县| 济南市| 阿拉尔市| 门头沟区| 陆良县| 扬中市| 鄱阳县| 泰安市| 麦盖提县| 乐清市| 盈江县| 广灵县| 米泉市| 辽中县| 波密县| 泾源县| 双城市| 莱州市| 禹城市| 沁阳市| 东丰县| 山阴县| 兴隆县| 武清区| 桃园市| 增城市| 房山区| 凤城市| 怀集县| 苗栗县| 黑山县| 纳雍县| 和顺县| 利辛县|