使用带有事件发射器的立即调用的函数表达式(IIFE)

时间:2015-01-14 08:59:24

标签: javascript node.js

我想对我如何编写以下代码进行健全性检查。该代码列出来自电子邮件帐户的3条消息,然后下载并解析每个消息正文,并将结果保存到Mongo数据库。虽然这是Node.js代码,但我认为我的问题一般是javascript。在我第一次尝试(下面显示的代码)时,相同的消息打印到控制台并被保存到数据库3次。预期的功能是将3个不同的消息保存到数据库中。我认为该问题与messages[x]没有通过变量"end"正确发送到发出的objMessageHeader事件有关,所以在第二个代码示例中我添加了一个IIFE(立即调用的函数)表达式)如图所示。现在,3条消息正确下载到数据库,而不是下载并将相同的消息保存3次到数据库。

我忍不住认为IIFE解决方案是hackish。这是正确的方法吗?这是一个反模式,是否有更好或不同的方式?如果您不确定如何回答,也许您可​​以解释为什么第一次尝试不起作用而第二次尝试不起作用。

注意:client.createMessageStream(... objMailParser)行最终会触发objMailParser的{​​{1}}事件。

这是我的第一次尝试,它无法正常工作并将相同的消息保存3次到数据库:

"end"

这是带有IIFE(立即调用的函数表达式)的修改后的代码,它可以正常工作,将3个单独的消息保存到数据库中:

client.listMessages(-3, function(err, messages){ 

    for (var x=0; x <= messages.length-1; x++) { 

        var objMessageHeader = messages[x];

        var objMailParser = new MailParser(); 

        objMailParser.on("end", function(objParsedMessage){
            console.log("["+objMessageHeader.UIDValidity+"."+objMessageHeader.UID+"] Subject: <"+objMessageHeader.title+"> Flags: <"+objMessageHeader.flags+">");
            console.log("---------------------------------------------------------<<<");
            console.log("From:", objParsedMessage.from);
            console.log("Subject:", objParsedMessage.subject);
            console.log("Text body:", objParsedMessage.text);
            console.log(">>>---------------------------------------------------------");

            var objMessage = objMessageHeader;
            objMessage.type = "message";
            objMessage.account = "someemail@yahoo.com";
            objMessage.mailboxPath = strMailboxPath;

            objMessage.parsedMessage = objParsedMessage;

            saveMessageToDBMongo("first100", strMailboxPath, collMessages, objMessage);

        }); // objMailParser.on("end" ...

        client.createMessageStream(objMessageHeader.UID).pipe(objMailParser);

    } // for (var x=0 ...
}); // client.listMessages ...  

1 个答案:

答案 0 :(得分:0)

在循环闭包内只有一个x变量的副本,并且所有绑定都看到相同的值。如果要在绑定中使用x,则需要打破循环并为每个绑定使用新范围(这可以通过IIFE完成)。您的邮件正在保存3次,因为x始终为3

检查这个小提琴:http://jsfiddle.net/vc149s70/

如果查看setTimeout()控制台日志,结果始终为test3,但在MailParser()超时时结果是正确的。

使用IIFE是解决此问题的正确方法,因为您只需创建新范围并传入x。还有很多其他方法可以做到这一点,但我认为在你的情况下,IIFE是好的。