{"id":19018789,"url":"https://github.com/shalvah/aargh","last_synced_at":"2025-04-23T04:39:47.976Z","repository":{"id":57171768,"uuid":"182616597","full_name":"shalvah/aargh","owner":"shalvah","description":"Selectively handle errors in JavaScript","archived":false,"fork":false,"pushed_at":"2020-07-31T10:13:11.000Z","size":62,"stargazers_count":84,"open_issues_count":0,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-11T13:58:12.310Z","etag":null,"topics":["error-handling","errors","javascript"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shalvah.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-22T03:28:16.000Z","updated_at":"2024-10-24T15:29:02.000Z","dependencies_parsed_at":"2022-08-24T14:40:49.117Z","dependency_job_id":null,"html_url":"https://github.com/shalvah/aargh","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalvah%2Faargh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalvah%2Faargh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalvah%2Faargh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalvah%2Faargh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shalvah","download_url":"https://codeload.github.com/shalvah/aargh/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250372692,"owners_count":21419720,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["error-handling","errors","javascript"],"created_at":"2024-11-08T20:10:06.818Z","updated_at":"2025-04-23T04:39:47.956Z","avatar_url":"https://github.com/shalvah.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# aargh\nYep. That's the sound of a man who just got dumped by his girlfriend, chewed by a bear and then shot 32 times. It's also the sound I make when working with JavaScript.\n\nLol, just kidding. It's *one* of the sounds I make when working with JavaScript. Aaaaaaargh.\n\n[![npm version](https://badge.fury.io/js/aargh.svg)](https://badge.fury.io/js/aargh)\n[![Build Status](https://travis-ci.com/shalvah/aargh.svg?branch=master)](https://travis-ci.com/shalvah/aargh)\n[![npm](https://img.shields.io/npm/dt/aargh)](https://www.npmjs.com/package/aargh)\n\n## Why, what, who is this?\nThis module gives you a simple way to selectively handle errors in JavaScript.\n\nSupposing you have a function like this:\n\n```javascript\nfunction fetchTweets (userId) {\n    return twitterApi.fetch(userIdd).then(response =\u003e {\n        if (response.error \u0026\u0026 response.error.message.includes(\"Too many requests\")) {\n            throw new RateLimitExceededError();\n        }\n        return response.data;\n    })\n}\n```\n\nThis function is meant to throw a specific error when you exceed your Twitter API rate limits. (`RateLimitExceededError` is a custom Error class you created.)\n\nSo you call it like this:\n\n```javascript\nfetchTweets(userId)\n  .catch(e =\u003e {\n      console.log('Rate limit exceeded; initiating exponential backoff');\n      // do backoff\n  })\n  .then(tweets =\u003e {\n      // do stuff with them\n  })\n```\n\nor...\n\n```javascript\ntry {\n    let tweets = await fetchTweets(userId);\n} catch(e) {\n      console.log('Rate limit exceeded; initiating exponential backoff');\n      // do backoff\n}\n```\n\nSee the problem? Different errors could be thrown in that function. For instance, if you look closely at the function, you'll see I made a typo on the first line (`userIdd` instead of `userId`) which will throw a `ReferenceError` (internal JavaScript error) when executed. However, the calling code will expect a `RateLimitError` only.\n\nThere's a simple fix: use an if-statement:\n```javascript\ntry {\n    let tweets = await fetchTweets(userId);\n} catch(e) {\n    if (e instanceof RateLimitExceededError) {\n      console.log('Rate limit exceeded; initiating exponential backoff');\n      // do backoff\n    } else if (e instanceof SomeOtherError || e instanceof SomeOtherAnnoyingError) {\n        // handle it\n    } else {\n        // this is important, so unexpected errors \n        // don't get swallowed by our app\n        throw e;\n    }\n}\n```\n \nHey, if that works for you, well, good, but if you're like me, you hate writing this kind of `if` statement. Too messy. I prefer PHP's inbuilt selective error handling:\n\n```php\ntry {\n    $tweets = fetchTweets($userId);\n} catch(RateLimitExceededError $e) {\n    echo 'Rate limit exceeded; initiating exponential backoff';\n     // do backoff\n} catch (SomeOtherError | SomeOtherAnnoyingError $e) {\n    // handle it\n}\n\n// Any error that doesn't match the types you specified is not caught\n```\nSo I decided to do something similar for JS. Here's how you use it:\n\n```javascript\ntry {\n    let tweets = await fetchTweets(userId);\n} catch(e) {\n    return aargh(e)\n        .handle(RateLimitExceededError, (e) =\u003e {\n            console.log('Rate limit exceeded; initiating exponential backoff');\n            // do backoff\n        })\n        .handle([SomeOtherError, SomeOtherAnnoyingError], (e) =\u003e {\n            // handle it\n        })\n        .throw();\n}\n```\n\nWorks with Promise#catch() too:\n\n```javascript\nfetchTweets(userId)\n  .catch(e =\u003e {\n      return aargh(e)\n          .handle(RateLimitExceededError, (e) =\u003e  {\n              console.log('Rate limit exceeded; initiating exponential backoff');\n              // do backoff\n          })\n          .handle([SomeOtherError, SomeOtherAnnoyingError], (e) =\u003e {\n              // handle it\n          })\n          .throw();\n  })\n  .then(tweets =\u003e {\n      // do stuff with them\n  })\n```\n\n## Usage\n```javascript\nconst aargh = require('aargh');\n```\n### aargh(e)\n\nThe entry point. You pass in the error object you want to handle. You should probably have this as the first statement in all your catch() blocks.\n\n### .handle(errorTypes, callback)\nThe first argument to the `handle` function is the type or types (as an array) of errors you want to handle. The second is a callback containing the code you want to execute for that error. Aargh will call this callback with the error as the only parameter. \n\nYou can return stuff from this callback too. Aargh will return this value to the caller.\n\n### .throw()\nCalling the `throw()` function ends the chain and ensures any errors which weren't matched by your `handle()` checks are thrown back to the caller.\n\n### .others(callback)\nUse the `others()` function to end the chain and specify a callback to be executed if the error wasn't matched by your `type()` checks. You should use either `throw()` or `others()`, and it should only be used after all `type()` calls.\n\n```javascript\ntry {\n    return await fetchTweets(userId);\n} catch(e) {\n    return aargh(e)\n        .handle(RateLimitExceededError, (e) =\u003e {\n            // do backoff\n        })\n        .handle(APIUnavailableError, (e) =\u003e {\n          // backoff nicely\n        })\n        .others((e) =\u003e {\n            // This will catch any other errors\n            // Maybe log the error? Idk\n        });\n}\n```\n## Want to try it out?\n\n```npm i aargh```\n\n## Hey, I'd like your opinion\nI spent time thinking about the most intuitive/natural syntax/flow to use for this. If you're interested in this package, and you've got ideas, please hit me up [on Twitter](twitter.com/theshalvah) or open an issue.\n\n## Don't forget\nA few tips for error handling in JS (whether you're using this package or if-statements):\n- Create your custom errors. Don't throw strings or just `Error`. **Why?** So you can trace exactly what went wrong in your code.\n- Make sure your errors extend from the `Error` class. **Why?** So you can leverage all the awesome debugging tools out there, plus inbuilt Error properties like `.stack`.\n- Handle only errors you expect. Let the rest crash your app. **Why?** So you know when something goes wrong.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshalvah%2Faargh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshalvah%2Faargh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshalvah%2Faargh/lists"}