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.

Reply via email to