2015-08-15 145 views
0

我正在使用app使用node-imap,並且我一直在處理錯誤或缺少錯誤時遇到了困難。我有以下功能:錯誤與錯誤拒絕與藍鳥。解決就好了。錯誤似乎崩潰了應用程序

////imap-helpers.js 
function searchBox(searchTerm, bodies){ 
    return new Promise(function(resolve, reject){ 
    searchTerm = searchTerm || ['ALL'] 
    bodies = bodies || ['HEADER.FIELDS (FROM TO CC BCC SUBJECT)','TEXT'] 
    imap.search(searchTerm, function(err, results){ 
     if (err) reject(err) 
     var messages = [], newMessage = {}, count=0; 
     var f = imap.fetch(results, { 
     bodies: bodies, 
     struct: true 
     }); 

     f.on('message', function(msg) { 
     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[count] = _.omit(newMessage, 'rawHeader') 
      count++ 
     }) 

     }) 

     f.on('error', function(e){ 
     reject(e) 
     }) 

     f.once('end', function(){ 
     resolve(messages) 
     }) 

    }) 
    }) 
} 

exports.getByUID = function(boxName, uid){ 
    boxName = boxName || 'INBOX' 
    var searchTerm = ['ALL',['UID',uid]] 
    return imap.openBoxAsync(boxName, false).then(function(){ 
    return searchBox(searchTerm, ['HEADER.FIELDS (FROM TO CC BCC SUBJECT)']).then(function(messages){ 
     return messages 
    }).catch(function(e){ 
     throw e 
    }) 
    }).catch(function(e){ 
    return e 
    }) 
} 

然後我可以在文件中調用它。

//imap-controller.js - severely amended version 
    getOne: function(req, res){ 
    methods.getByUID('INBOX',req.params.uid).then(function(response){ 
     res.json(response) 
    }).catch(function(e){ 
     res.json({error: e.message}) 
    }) 
    } 

但問題是我沒有運氣返回到控制器的錯誤。它只是不斷地打破了

Unhandled rejection Error: Nothing to fetch 
    at Connection._fetch (/Users/dkranec/github/imap/node_modules/imap/lib/Connection.js:778:11) 
    at Connection.fetch (/Users/dkranec/github/imap/node_modules/imap/lib/Connection.js:771:15) 
    at Connection.tryCatcher (/Users/dkranec/github/imap/node_modules/bluebird/js/main/util.js:26:23) 
    at Connection.ret [as fetchAsync] (eval at <anonymous> (/Users/dkranec/github/imap/node_modules/bluebird/js/main/promisify.js:163:12), <anonymous>:15:23) 
    at /Users/dkranec/github/imap/app.js:34:12 
    at tryCatcher (/Users/dkranec/github/imap/node_modules/bluebird/js/main/util.js:26:23) 
    at Promise._settlePromiseFromHandler (/Users/dkranec/github/imap/node_modules/bluebird/js/main/promise.js:503:31) 
    at Promise._settlePromiseAt (/Users/dkranec/github/imap/node_modules/bluebird/js/main/promise.js:577:18) 
    at Promise._settlePromises (/Users/dkranec/github/imap/node_modules/bluebird/js/main/promise.js:693:14) 
    at Async._drainQueue (/Users/dkranec/github/imap/node_modules/bluebird/js/main/async.js:123:16) 
    at Async._drainQueues (/Users/dkranec/github/imap/node_modules/bluebird/js/main/async.js:133:10) 
    at Immediate.Async.drainQueues [as _onImmediate] (/Users/dkranec/github/imap/node_modules/bluebird/js/main/async.js:15:14) 
    at processImmediate [as _immediateCallback] (timers.js:371:17) 

請看到相關reddit的文章中,我對這個話題該功能的應用程序我做了也有問題的小版本所做這裏,如果你認爲你可以與here幫助程序。基本上同一個問題的另一個版本,但捕捉錯誤,但沒有放出imap.fetch發射器成功。我贏不了!

+1

井,至少'如果(ERR)拒絕(ERR)'應該是'如果(ERR){拒絕(ERR) ;返回; }' –

+0

什麼是'imap.openBoxAsync'?這是你寫的一個函數嗎?如果是這樣,你需要顯示它。 –

+0

你確定'var newMessage ...'在正確的範圍內嗎?正如所寫的,每個'f.on('message'...'將導致先前的'newMessage'被覆蓋,並且流只會將它們的塊貢獻給最後創建的'newMessage' - 這至少可能是錯誤的!我會認爲'var newMessage ...'應該在'f.on('message'...'作用域中 –

回答

0

searchBox()最主要的事情是return;之後reject(err);,正如@KirillSlatin在上面評論中所說。

這裏的整體功能與一些進一步的(未經測試)建議:

function searchBox(searchTerm, bodies) { 
    return new Promise(function(resolve, reject) { 
     searchTerm = searchTerm || ['ALL']; 
     imap.search(searchTerm, function(err, results) { 
      if (err) { 
       reject(err); 
       return; // <<<<<<<<<<<<<<<<<<< 
      } 
      var messages = [], 
       f = imap.fetch(results, { 
        bodies: bodies || ['HEADER.FIELDS (FROM TO CC BCC SUBJECT)','TEXT'], 
        struct: true 
       }); 
      f.on('message', function(msg) { 
       var rawHeader = '', 
        newMessage = { body: '' }; 
       msg.on('body', function(stream, info) { 
        stream.on('data', function(chunk) { ((info.which == 'TEXT') ? newMessage.body : rawHeader) += chunk.toString('utf8') }); 
        // stream.once('end', function() { });//no point doing anything here providing msg.once('end') fires later. 
       }); 
       msg.once('attributes', function(attrs) { newMessage.attrs = attrs; }); 
       msg.once('end', function() { 
        newMessage.header = rawHeader.length ? Imap.parseHeader(rawHeader) : ''; 
        newMessage.attrs = newMessage.attrs || [];//safety 
        messages.push(newMessage); 
       }); 
      }); 
      f.on('error', reject); 
      f.once('end', function() { resolve(messages); }); 
     }); 
    }); 
} 

隨着f.on('message')處理程序內聲明newMessage,還有當嵌套事件發生的任何消息的機會串擾,不論性質事件分派 - 同步或異步。

而且.getByUID()將在任何錯誤傳遞,而不需要捕捉/重新拋出:

exports.getByUID = function(boxName, uid) { 
    return imap.openBoxAsync(boxName || 'INBOX', false).then(function() { 
     return searchBox(['ALL', ['UID', uid]], ['HEADER.FIELDS (FROM TO CC BCC SUBJECT)']); 
    }); 
} 
+0

有趣。我發現我的問題在於'imap.fetch()'函數的寫法。它不是爲了處理回調風格而編寫的。它要麼通過'return new EventEmitter()'返回事件發射器,要麼完全通過'throw new Error()'失敗。我不認爲這些錯誤將被優雅地處理,無論藍鳥如何處理。我可能必須爲該函數編寫一個自定義promisification處理程序。 – dkran

+0

我嘗試了'try {var f = imap.fetch()...} catch(e){console.log(e);拒絕(E);返回; },它可以正確記錄錯誤而不會崩潰我的應用程序,但不會拒絕...爲什麼? – dkran

+0

令人沮喪的是'imap.fetch()'不遵循與'imap.search()'相同的節點模式。 該文檔沒有指出某些/任何'imap.fetch()'錯誤不會引起一個明顯的'錯誤'事件。 想法:文檔中的所有示例都使用'.once('error'...)'not'.on('error'...)'。 –