编程语言爱好者程序园Nodejs

Nodejs下实现邮件的同步读取 2

2019-05-14  本文已影响0人  赵阳_c149

之前的一篇文章中介绍了在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

上一篇 下一篇

猜你喜欢

热点阅读