如何在Node.js中结合来自不同callback的数据?

我有多个函数在接收/parsing数据时被callback,我需要一个callback中的数据匹配到来自另一个callback的数据,这些数据发生在不同的时间。

例如,我有以下代码来使用pipedrive / inbox(github) client和andres9 / mailparser(github) mailparser接收电子邮件:

 // List newest 10 messages client.listMessages(-5, function(err, messages){ messages.forEach(function(message){ var mailparser = new MailParser(); // setup an event listener when the parsing finishes mailparser.on("end", function(mail_object){ console.log("---------------------------------------------------------<<<"); console.log("Text body:", mail_object.text); // How are you today? console.log(">>>---------------------------------------------------------"); }); console.log(message.UID + ": Subject: < " + message.title + "> Flags: <" + message.flags + ">"); client.createMessageStream(message.UID).pipe(mailparser); //send the current email to the parser }); }); 

问题是,控制台显示消息的标题和标志一个接一个,首先,然后显示所有parsing的机构:

 884: Subject: <[eBook] Executive's Guide to the Top 20 CSCs> Flags: <> 888: Subject: <Free Cloud-based Vulnerability Scanner> Flags: <\Seen> 896: Subject: <Unexpected sign-in attempt> Flags: <\Seen> 902: Subject: <[Watch] Backoff POS Malware: Key Indicators of Compromise> Flags: <$NotJunk> 918: Subject: <test subject 1> Flags: <$NotJunk> [... Then here are all the bodies ...] [... Message #884's body ...] [... Message #888's body ...] [... and so on ..] 

当我想要

 884: Subject: <[eBook] Executive's Guide to the Top 20 CSCs> Flags: <> [... Then message #884's body ...] 888: Subject: <Free Cloud-based Vulnerability Scanner> Flags: <\Seen> [... Then message #888's body ...] 

最终,我将有这个应用程序发送完整的parsing消息(连同他们的parsing标题)到数据库,也浏览器,我需要的标志和其他元数据/头与parsing的身体配对,当我这样做,不逻辑分离通过callback。

Node.js中的最佳做法是什么? 对于相同的逻辑实体处理单独callback的标准方法是什么?有没有不同的方法来处理这个问题?

只要做end听众的所有工作:

 client.listMessages(-5, function(err, messages){ messages.forEach(function(message){ var mailparser = new MailParser(); // setup an event listener when the parsing finishes mailparser.on("end", function(mail_object){ console.log(message.UID + ": Subject: < " + message.title + "> Flags: <" + message.flags + ">"); console.log("---------------------------------------------------------<<<"); console.log("Text body:", mail_object.text); // How are you today? console.log(">>>---------------------------------------------------------"); }); client.createMessageStream(message.UID).pipe(mailparser); //send the current email to the parser }); }); 

这个很容易,因为你的调用是嵌套的。 有时你有多个asynchronous操作,一旦完成,你想要采取行动。 在这种情况下,使用蓝鸟这样的承诺库,并调用Promise.all()

只需将显示主题的console.log语句移动到显示主体的callback即

 mailparser.on("end", function(mail_object){ console.log(message.title); console.log("---------------------------------------------------------<<<"); console.log("Text body:", mail_object.text); // How are you today? console.log(">>>---------------------------------------------------------"); 

加上gilly3的优秀答案,您可能需要显示从最新到最旧的数据。 我的示例使用messages.length作为开始键来构build一个对象,然后为每个消息递减它,直到达到“1”,这将是最新的/最新的消息。 然后很容易将对象从1循环到lastkey以正确输出。

  // list newest 2 messages client.listMessages(-2, function(err, messages){ var newob = {}; var i = messages.length; messages.forEach(function(message){ var mailparser = new MailParser(); mailparser.on("end", function(mail_object){ console.log(message.UID+' '+message.title); /* because of loop direction i=1 will be latest/newest message to get last key we can use lastkey = Object.keys(newob).length; then loop from 1 to lastkey to output newest to last message. */ newob[i] = {}; newob[i]['UID'] = message.UID; newob[i]['from'] = mail_object.from; newob[i]['subject'] = mail_object.subject; newob[i]['title'] = message.title; newob[i]['text'] = mail_object.text; // count down 'i' so we know when at last message (i=0) i--; //now we're at end we can send object if(i===0){ endResponse(newob); } }); client.createMessageStream(message.UID).pipe(mailparser); }); });