OK I came up with a solution. It's based on closures from @Brenden Ashworth 's suggestion. It's untested but I'm fairly certain it would work, and I wanted to post this before I moved on as I found I didn't need to do what the original question described to get my project working.
However, I still think it is useful to have a solution to this type of problem as the need could arise, and I don't know a better solution.
Here's my solution:
//using andris9/mailparser on github
var mailparser = new MailParser({
streamAttachments: true
}
var UIDfromOnEndFuntion;
var myAttachment;
var intNumberOfEmitsToEndAndAttachment = 0;
var funcBothEndAndAttachmentEmitted = function () {
var output = fs.createWriteStream("attachments/"
+ UIDfromOnEndFuntion + "/" + myAttachment.generatedFileName);
//UIDfromEndFunction should be garaunteed to be
//populated by .once("end",...)
myAttachment.stream.pipe(output);
//myAttachment should be gauranteed to be populated
//by .once("attachment",...)
}
mailparser.once("end", function(objMail){
UIDfromOnEndFuntion = objMail.UID;
saveToDB("mail" + "1234", objMail);
intNumberOfEmitsToEndAndAttachment++;
if (intNumberOfEmitsToEndAndAttachment == 2) {
funcBothEndAndAttachmentEmitted();
}
});
mailparser.once("attachment", function(attachment){
myAttachment = attachment;
intNumberOfEmitsToEndAndAttachment++;
if (intNumberOfEmitsToEndAndAttachment == 2) {
funcBothEndAndAttachmentEmitted();
}
});
Now this would only work for a single emitted "end" and a single emitted "attachment".
You could get more creative with how the tracking is done to handle multiple attachments. For example, instead of using an integer to track the total number of calls, an array of objects could be used like [{"attachment",attachment_args1},{"attachment",attachment_args2},{"end",end_args2}]
to do the tracking of calls (this would mean attachment
has been called twice so far, and "end"
once, for example, and you could trigger a function based on that knowledge like I do by calling funcBothEndAndAttachmentEmitted()
).
I think this needs to be cleaned up and made into a library, unless there is a better way to do it that's not apparent. (Please comment if you know a better solution or I might go ahead and write a library for this solution.)
Another solution I thought of that might work is putting mailparser.once("attachment"...)
inside of the callback for mailparser.once("end"...)
but I suspect that wouldn't work if "attachment"
is emitted first, and this solution seems a bit cludgey compared to a library-based solution if you're working with many different emitted events for some reason or different objects emitting different events.