Nodejs下實現郵件的同步讀取 2

之前的一篇文章中介紹了在Nodejs下如何實現郵件的同步讀取【1】,基於imap,對與庫中的方法用wrap進行了包裝,實現了同步行。但是,從代碼的實現來看,仍然存在着兩個問題。首先是實現同步關閉連接的方法必須和讀取郵件的“配對使用”。 其次,當多次調用讀取郵件的方法時候,會引起emitter MaxListeners error。

對於第一個問題可以修改結束imap連接的方法,使其在郵件讀取和解析完成之後執行,也就是說作爲回調函數放入promise鏈:

async function endAsync(message = null) {    return new Promise(function (resolve, nay) {        imap.on('end', function () {            resolve(message);        });        imap.end();    });}

…
).then(function (messages) {    return endAsync(messages[messages.length - 1]);}).then(function (message) {    return message;})    .catch(function (error) {        console.error("Oops:", error.message);        imap.end();    })

對於第二個問題,錯誤的信息是:

(node:3133) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 end listeners added. Use emitter.setMaxListeners() to increase limit

在nodejs的官方文檔上可以找到相應的說明:

By default EventEmitters will print a warning if more than 10 listeners are added for a particular event. This is a useful default that helps finding memory leaks.

默認情況下,當爲同一個事件添加了超過10個listener的時候,就會打印出一條警告信息。這一默認行爲有助於發現內存泄漏。

正向我之前的一篇文章【2】中講到的,Javascript中,javascript runtime還維護着第三類內存空間,事件隊列(Queue),因此不得不將事件的listener考慮到內存管理的範疇之內。但是並不想通過增加允許的listener數量來回避這個問題,因爲有一種更好的辦法。

Using the eventEmitter.once() method, it is possible to register a listener that is called at most once for a particular event. Once the event is emitted, the listener is unregistered and then called.

當用once註冊listener的時候,它只會爲一個特定的事件調用一次,一旦事件觸發了,listener同樣會被觸發,但是之後就會被刪除。

async function endAsync(message = null) {    return new Promise(function (resolve, nay) {        imap.once('end', function () {            resolve(message);        });        imap.end();    });}

解決了這兩個問題之後,回看這個簡單的例子不難發現,imap對象是一個全局變量,或者說是一個singleton模式的應用,所以纔會有setMaxListeners的問題。

const imap = new Imap({    user: 'user',    password: 'password',    port: 993,    host: 'host',    tls: true});

通過這兩篇文章介紹,讀者應該可以瞭解我是如何實現Nodejs下郵件的同步讀取。並且,文章描述了在這一過程中出現的問題和相應的解決方法。

實例代碼可以在github上找到【3】。

【1】Nodejs下實現郵件的同步讀取 1
【2】Nodejs Event Loop
【3】test_imap_sample_end_once.js

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章