Coffeescript with callbacks and simplified error handling

I would like to be able to reorganize the error handling from this coffeescript code:

# Do some stuff with 2 levels of asynchronous callbacks and error handling vote = (res, data) -> Case.findOne { caseId: data.id }, (err, mycase) -> if err console.error 'Vote failed' else myvote = new Vote case: mycase._id myvote.save (err) -> if err console.error 'Could not add vote' else console.log 'Success!' 

like that:

 # Run my function, do error handling, and run the callback if no error runit = (func, arg, errmsg, callback) -> func arg, (err, docs) -> if err console.log errmsg + ': ' + err else callback docs # Original code, simplified vote = (res, data) -> runit Case.findOne { caseId: data.id }, 'Vote failed', (mycase) -> myvote = new Vote case: mycase._id runit myvote.save, 'Could not add vote', () -> console.log 'Success!' 

Obviously, the runit function should be able to handle one or more arguments correctly, which I did not try to code correctly.

If I run it like this, I get an error message:

 node.js:201 throw e; // process.nextTick error, or 'error' event on first tick ^ TypeError: Cannot read property 'findOne' of undefined at /tmp/node_modules/mongoose/node_modules/hooks/hooks.js:27:28 at /tmp/lib/api.js:227:12 at Promise.<anonymous> (/tmp/lib/api.js:216:16) at Promise.<anonymous> (/tmp/node_modules/mongoose/lib/promise.js:120:8) at Promise.<anonymous> (events.js:67:17) at Promise.emit (/tmp/node_modules/mongoose/lib/promise.js:59:38) at Promise.complete (/tmp/node_modules/mongoose/lib/promise.js:70:20) at /tmp/node_modules/mongoose/lib/query.js:885:15 at model.<anonymous> (/tmp/node_modules/mongoose/lib/document.js:181:5) at model.init (/tmp/node_modules/mongoose/lib/model.js:181:36) 
+4
source share
3 answers
 # Run my function, do error handling, and run the callback if no error runit = (func, args..., errmsg, callback) -> func args..., (err, docs) -> if err return console.log errmsg + ': ' + err callback docs # Original code, simplified vote = (res, data) -> runit Case.findOne { caseId: data.id }, 'Vote failed', (mycase) -> myvote = new Vote case: mycase._id runit myvote.save, 'Could not add vote', -> console.log 'Success!' 

What runit compiles to:

 runit = function() { var args, callback, errmsg, func, _i; func = arguments[0], args = 4 <= arguments.length ? __slice.call(arguments, 1, _i = arguments.length - 2) : (_i = 1, []), errmsg = arguments[_i++], callback = arguments[_i++]; return func.apply(null, __slice.call(args).concat([function(err, docs) { if (err) return console.log(errmsg + ': ' + err); return callback(docs); }])); }; 
+3
source

Use early returns instead of conditional branches, this way you keep your code simple and reasonable and avoid an unnecessary template.

 vote = (res, data) -> Case.findOne { caseId: data.id }, (err, mycase) -> return console.error 'Vote failed' if err? myvote = new Vote case: mycase._id myvote.save (err) -> return console.error 'Could not add vote' if err? console.log 'Success!' 
+2
source

I am a big fan of the Canon Asynchronous Library . The big idea with this library is that the first argument of each callback is an error, and if there is no error, the next function in the chain is called. So you could look like this:

 vote = (res, data) -> async.series [ (next) -> Case.findOne { caseId: data.id }, next (next) -> myvote = new Vote({case: mycase_id}).save(next) ], (err, result) -> if err console.error err else console.log "Success!" 

The function chain breaks on the first error, so your last callback is really only responsible for handling one error. This is great for sequential processes in which you want to stop and report the first problem you encounter.

+1
source

Source: https://habr.com/ru/post/1389883/


All Articles