0

Can't figure how to selectively handle an error in a promise chain...

I'm not sure when should I return a new promise (with new, or promise.reject or promise.fulfill), how to break the chain (return promise.reject or throw?), and which rejection is caught by .done — and how to only handle some errors in .done?

(Localization would be nice, ie, avoiding global variables, like I had in callback hell before. Also, keep error handling near cause, unless handled collectively.)

Context: Express route handler for "/save" with somewhat complex logic, and optionally promisified LevelDB.

promise=require 'promise' # (Capitalize Promise in anticipation of ES6?)
db=(require 'level-promise') sub (require 'level') './data',keyEncoding:'utf8',valueEncoding:'json'

Simplified untested pseudocode (CoffeeScript, obviously), eg:

.post '/save',(req,res)->
    new promise ->
        # Validations… Sync stuff.
        unless req.body.role then return promise.reject res.send 400,'Missing role.'
        # Etc.
        promise.fulfill()
    .then ->
        # Permissions, similarly, but 403...

    .then ->
        # But what about async stuff?
        # If changing username, ensure availability.
        return new promise (fulfill,reject)->
            if key_change
                db.get r.username,(err,v)-> # Why not promisified/denodeify?!
                    unless err?.notFound then reject res.send 400,'Username already taken.' # Throw instead?
                    else
                        changes.push type:'del',key:r.current_username
                        fulfill() # ?
            else fulfill() # ?
            # Or .catch here?

    # .catch here?
    .then ->
        # Etc.
    .then ->return db.batch changes # Promisified?

    # Error handling for everything (that wasn't already).
    .done ->res.send 200,'Saved.'
    ,-> # Which rejection caught here?
        res.send 500,'Oops...'

    # Or better?
    .then ->res.send 200,'Saved.'
    .catch -> # Which rejection caught here?
        res.send 500,'Oops...'
    .done() # Because catch doesn't end chain?

Thanks!

PS: http://www.html5rocks.com/en/tutorials/es6/promises/ seems helpful, but I still haven't digested it. Seems to suggest I need to add .catch'es inside the chain? But How to stop/break in the middle of chained promises suggests catching the inner promise instead?

Community
  • 1
  • 1
Dream
  • 28
  • 3
  • 1
    http://stackoverflow.com/questions/26076511/handling-multiple-catches-in-promise-chain seems to answer this, but uses Bluebird instead of the promise module, so I'm not sure… – Dream Nov 29 '14 at 11:56
  • promise module: https://www.promisejs.org/ – Dream Nov 29 '14 at 12:03
  • My answer there fits here just the same and you can use it. Moreover you should consider not using the promise module and use Bluebird instead - it is much faster and gives much better stack traces. – Benjamin Gruenbaum Nov 30 '14 at 20:17

1 Answers1

0

Nu. I ended up throwing/rejecting to break the chain, and relying on done/catch receiving an exception/rejected value explicitly to distinguish unhandled "exceptions": http://decodecode.net/elitist/2014/12/levelup-promises-promises/

Apparently, there's no better control flow structure available yet?

Dream
  • 28
  • 3