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

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

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

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

注意:
client.createMessageStream(…objMailParser)
行最终触发
objMailParser
“end”
事件

这是我第一次尝试,但没有正常工作,并将同一消息保存到数据库中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 ...  
client.listMessages(-3, function(err, messages){ 

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

        //var objMessageHeader = messages[x];

        (function iifeParseMessageBody(objMessageHeader){
            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 = "neatcode@yahoo.com";
                objMessage.mailboxPath = strMailboxPath;

                objMessage.parsedMessage = objParsedMessage;

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

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

            client.createMessageStream(objMessageHeader.UID).pipe(objMailParser);
        }.call(this, message_header_super));

    } // for (var x=0 ...
}); // client.listMessages ...  
client.listMessages(-3,函数(err,messages){

对于(var x=0;x当在循环闭包中时,只有一个x变量的副本,并且所有绑定都看到相同的值。如果要在绑定中使用
x
,则需要中断循环,并为每个绑定使用新的作用域(这可以通过IIFE完成)。您的邮件保存了3次,因为
x
始终是
3

检查这把小提琴:

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

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