I have a node issue where I'm using the imap
module, and I am trying to return a promise. I have created a Promise.method()
using bluebird. The code is actually available at:
https://github.com/dkran/email-thinky-test/
So my issue is I have this file performing this:
//file: ./imap/helper.js
var Imap = require('imap'),
Promise = require('bluebird'),
imap = require('../util/imap');
exports.parseMailbox = Promise.method(function(boxName){
boxName = boxName || 'INBOX'
imap.openBoxAsync(boxName, false).then(function(inbox){
var messages = [], newMessage = {};
imap.searchAsync(['ALL']).then(function(results){
var f = Promise.promisifyAll(imap.fetch(results, {
bodies: ['HEADER.FIELDS (FROM TO CC BCC SUBJECT)','TEXT'],
struct: true
}));
f.on('message', function(msg, seqno) {
newMessage = {}
msg.on('body', function(stream, info) {
//When we get a message, append the header to header, text to body.
stream.on('data', function(chunk){
if (info.which !== 'TEXT')
newMessage.rawHeader += chunk.toString('utf8')
else
newMessage.body += chunk.toString('utf8')
})
//When stream is done, strip the unparsable characters at the beginning before parsing.
//NOTE: I'm not actually sure what these unparseable characters actually are
//but this all works kosher.
stream.once('end', function() {
if (info.which !== 'TEXT'){
newMessage.rawHeader = newMessage.rawHeader.replace(/^undefined/, '')
newMessage.header = Imap.parseHeader(newMessage.rawHeader)
}
if(newMessage.body)
newMessage.body = newMessage.body.replace(/^undefined/, '')
})
})
msg.once('attributes', function(attrs) {
newMessage.attrs = attrs
})
msg.once('end', function() {
messages[seqno-1] = newMessage
})
});
f.once('error', function(err) {
throw err
});
return f.onceAsync('end').then(function() {
console.log('Messages: ' + messages.length)
return messages
})
}).catch(function(e){
throw e
})
}).catch(function(e){
throw e
})
})
module.exports = exports
and then another little file doing this:
//file: ./imap/index.js
var imap = require('../util/imap'),
mail = require('./mail'),
mailHelpers = require('./helpers');
imap.onceAsync('ready').then(function(){
imap.getBoxesAsync().then(function(result){
for(var box in result){
mail.mailboxes.push(box)
}
}).catch(function(e){
console.log(e)
}).finally(function(){
mailHelpers.parseMailbox('INBOX').then(function(res){
mail.mail = res
console.log('res: ' + res)
console.log('mail: ' + mail.mail)
console.log(mail.mailboxes)
}).catch(function(e){
console.log(e)
})
})
})
At the bottom of the helper file when the 'end' event triggers, and the console.log goes off, it says I have 9 messages (which is true.) if I log the messages there instead it shows them all in the object. but they never get returned it's always undefined. Why is this? All of my other callbacks I converted seemed to work fine.
exact output I get is:
res: undefined
mail: undefined
[ 'INBOX', 'Sent Messages', 'Deleted Messages', 'Drafts' ]
Messages: 9
答案 0 :(得分:0)
在这种情况下,您不想使用Promise.method
。只需返回一个在所有这些回调中得到解决的承诺。
//file: ./imap/helper.js
var Imap = require('imap'),
Promise = require('bluebird'),
imap = require('../util/imap');
exports.parseMailbox = function(boxName) {
return new Promise(function(resolve, reject) {
boxName = boxName || 'INBOX'
imap.openBoxAsync(boxName, false).then(function(inbox) {
var messages = [],
newMessage = {};
imap.searchAsync(['ALL']).then(function(results) {
var f = Promise.promisifyAll(imap.fetch(results, {
bodies: ['HEADER.FIELDS (FROM TO CC BCC SUBJECT)', 'TEXT'],
struct: true
}));
f.on('message', function(msg, seqno) {
newMessage = {}
msg.on('body', function(stream, info) {
//When we get a message, append the header to header, text to body.
stream.on('data', function(chunk) {
if (info.which !== 'TEXT')
newMessage.rawHeader += chunk.toString('utf8')
else
newMessage.body += chunk.toString('utf8')
})
//When stream is done, strip the unparsable characters at the beginning before parsing.
//NOTE: I'm not actually sure what these unparseable characters actually are
//but this all works kosher.
stream.once('end', function() {
if (info.which !== 'TEXT') {
newMessage.rawHeader = newMessage.rawHeader.replace(/^undefined/, '')
newMessage.header = Imap.parseHeader(newMessage.rawHeader)
}
if (newMessage.body)
newMessage.body = newMessage.body.replace(/^undefined/, '')
})
})
msg.once('attributes', function(attrs) {
newMessage.attrs = attrs
})
msg.once('end', function() {
messages[seqno - 1] = newMessage
})
});
f.once('error', function(err) {
throw err
});
return f.onceAsync('end').then(function() {
console.log('Messages: ' + messages.length)
// just resolve it, lets not worry about returning promises 3 or 4 callbacks deep
resolve(messages)
})
}).catch(function(e) {
// pass the failure to the promise
reject(e)
})
}).catch(function(e) {
reject(e)
})
})
}
module.exports = exports
答案 1 :(得分:0)
根据我和@Bergi的谈话,我意识到我必须返回整个承诺链。像这样,它的工作原理:
exports.parseMailbox = function(boxName){
boxName = boxName || 'INBOX'
return imap.openBoxAsync(boxName, false).then(function(inbox){
var messages = [], newMessage = {};
return imap.searchAsync(['ALL']).then(function(results){
var f = Promise.promisifyAll(imap.fetch(results, {
bodies: ['HEADER.FIELDS (FROM TO CC BCC SUBJECT)','TEXT'],
struct: true
}));
f.on('message', function(msg, seqno) {
newMessage = {}
msg.on('body', function(stream, info) {
//When we get a message, append the header to header, text to body.
stream.on('data', function(chunk){
if (info.which !== 'TEXT')
newMessage.rawHeader += chunk.toString('utf8')
else
newMessage.body += chunk.toString('utf8')
})
//When stream is done, strip the unparsable characters at the beginning before parsing.
//NOTE: I'm not actually sure what these unparseable characters actually are
//but this all works kosher.
stream.once('end', function() {
if (info.which !== 'TEXT'){
newMessage.rawHeader = newMessage.rawHeader.replace(/^undefined/, '')
newMessage.header = Imap.parseHeader(newMessage.rawHeader)
}
if(newMessage.body)
newMessage.body = newMessage.body.replace(/^undefined/, '')
})
})
msg.once('attributes', function(attrs) {
newMessage.attrs = attrs
})
msg.once('end', function() {
messages[seqno-1] = newMessage
})
})
f.onceAsync('error').catch(function(err){
throw err
})
return f.onceAsync('end').then(function() {
console.log('Messages: ' + messages.length)
return messages
})
})
}).catch(function(e){
throw e
})
}
module.exports = exports
现在,承诺会像它应该的那样返回属性。