In addition to what Aria has said, I also think that encapsulating your
reponse into an object with `sucess` is not that well.
When writing a package, try writing API specs first, if not tests. For
example, this is what I'd expect.:
var api = require('my-cool-social-api-module');
api.getPosts(req.user._id); // no callback. ignored.
api.getPosts(null, callback); // no userId. I would expect callback
with error. Maybe not common Error, but custom, so I can test with err.name
=' MyApiError', err.message = 'Missing params.'.
api.getPosts(req.user._id, callback); // If I cannot get a response
from YOUR API, I'd expect an error. I don't care about HTTP statuses at
this point.
In any case, I would want normalized all errors as much as possible. Then
when _I_ write _my_ error handling from this module, I can be simple and
straight-forward:
function callback(err, result) {
if (err) {
if (err.name === 'ValidationError') {
// do one thing
} else if (err.name === 'CoolApiError') {
// your module failed
} else {
// third party error, if you need to pass it at all.
}
}
It may also be useful, if you're extending Error, to include something like
err.errorCode alongside err.name and err.message. Then when I message you
on twitter for a quick help, I have more then 'Server error'.
On Sunday, May 17, 2015 at 12:36:41 AM UTC+2, Owen Allen wrote:
>
> There's a lot of blog posts around the internet talking about the
> mechanics of handling errors, be it domains or
> process.on("uncaughtException"). I can't find much definitive talk about
> the philosophy of error handling though. Specifically when should a
> function return an error cb(err), or return an error state such as cb(null,
> { success : false, message : "Some useful message", resp : httpResponse }).
>
> In example, lets imagine we're creating a social media NPM package which
> has an async function which queries a social media API via an HTTP call
> using the popular request module and returns some posts. Our function takes
> 3 arguments a userid and a count and a callback. There are a variety of
> exit scenarios for this function:
>
> 1. Malformed arguments sent to the function such as a missing cb or a
> null/undefined/incorrectly formatted userid.
> 2. Unable to reach the service via HTTP.
> 3. Service returned a non-200 status code for some reason, maybe we're
> being rate-limited.
> 4. Reached the service, but the call failed at the service due to invalid
> parameters, some services return a 200 status code for this type of failure
> other's return a non-200 status code.
> 5. Reached the service, the call succeeded but returned an empty array of
> posts.
> 6. Reached the service, the call succeeded and returned data.
> 7. The function throws an unhandled error due to programmer mistake.
>
> Usually my philosophy for handling errors in this case would be:
>
> 1. cb(new Error("Invalid parameters, must pass a callback"));
> 2. cb(err); // the error that was returned by the http request
> 3. cb(null, { success : false, message : "Service returned a " +
> resp.statusCode + " status code", resp : resp });
> 4. cb(null, { success : false, message : serviceResponse.message, resp :
> resp });
> 5. cb(null, { success : true, data : [] });
> 6. cb(null, { success : true, data : posts });
> 7. Whoops, let error bubble up to the application employing our package
> and it will handle it or crash.
>
> That's just one way to approach the problem. It could be argued that cases
> 1 - 4 should all cb an error and that the error object should be packed
> with the additional data to help debug or be a custom error type. Yet at
> the same time some people argue it's a bad idea to pack additional
> non-standard keys on to Error objects because it results in inconsistency
> between Error objects and modules. If every npm module packed it's Error
> objects with custom keys wouldn't we end up in a pretty chaotic situation?
> In addition, if that error is thrown or console.error() those extra keys
> will not show up because of the native behavior of
> Error.prototype.toString().
>
> Yet another approach would be for 1 - 4 to return an error AND the
> additional data. Such as cb(new Error(serviceResp.message), { success :
> false, message : serviceResp.message, resp : resp }). This way downstream
> modules have the useful debugging information available, but we still end
> up treading down the error pathway of control flow structures such as async
> and promises. In example, in async if an error is returned it
> short-circuits all the way to the end.
>
> Any guidance on this subject?
>
--
Job board: http://jobs.nodejs.org/
New group rules:
https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules:
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to the Google Groups
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/nodejs/982a59ec-b581-4e5b-a8bb-457a3585f313%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.