https://github.com/bdsqqq/try
Don't let the Try Catch Tower of Terror destroy your beautiful one liners.
https://github.com/bdsqqq/try
async-await error-handling promise typescript
Last synced: 5 months ago
JSON representation
Don't let the Try Catch Tower of Terror destroy your beautiful one liners.
- Host: GitHub
- URL: https://github.com/bdsqqq/try
- Owner: bdsqqq
- License: mit
- Created: 2023-02-13T20:15:15.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2023-10-07T16:56:25.000Z (over 2 years ago)
- Last Synced: 2025-08-25T01:58:24.359Z (10 months ago)
- Topics: async-await, error-handling, promise, typescript
- Language: TypeScript
- Homepage: https://trytm.vercel.app
- Size: 177 KB
- Stars: 246
- Watchers: 1
- Forks: 9
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Try™
Don't let the Try Catch Tower of Terror destroy your beautiful one liners.
## Usage
```
npm install @bdsqqq/try
```
```TS
import { trytm } from "@bdsqqq/try";
const mockPromise = () => {
return new Promise((resolve, _) => {
setTimeout(() => {
resolve("hello from promise");
}, 1000);
});
};
const mockPromiseThatFails = () => {
return new Promise((_, reject) => {
setTimeout(() => {
reject(new Error("hello from promise"));
}, 1000);
});
};
const [data, error] = await trytm(mockPromise());
const [data2, error2] = await trytm(mockPromiseThatFails());
```
## Why does this exist?
Async await feels like heaven because it avoids the callback hell or Pyramid of Doom by writing asyncronous code in a line by line format:
```TS
function hell() {
step1((a) => {
step2((b) => {
step3((c) => {
// ...
})
})
})
}
async function heaven(){
const a = await step1();
const b = await step2(a);
const c = await step3(b);
// ...
}
```
Until error handling comes into play... Because then you end up with the Try-Catch Tower of Terror, where your beautiful one-liners magically expand to at least 5 lines of code:
```TS
async function Terror(){
let a;
let b;
let c;
try {
a = await step1();
} catch (error) {
handle(error);
}
try {
b = await step2(a);
} catch (error) {
handle(error);
}
try {
c = await step3(b);
} catch (error) {
handle(error);
}
// ...
}
```
An easy solution would be to append the `.catch()` method to the end of each promise:
```TS
async function easy(){
const a = await step1().catch(err => handle(err));
const b = await step2(a).catch(err => handle(err));
const c = await step3(b).catch(err => handle(err));
// ...
}
```
This approach solves the issue but can get a bit repetitive, another approach is to create a function that implements one Try Catch to replace all the others:
```TS
import { trytm } from "@bdsqqq/try"
async function awesome() {
const [aData, aError] = await trytm(step1());
if(aError) // ...
const [bData, bError] = await trytm(step2(aData));
if(bError) // ...
const [cData, cError] = await trytm(step3(bData));
if(cError) // ...
// ...
}
```
### Why does this REALLY exist?
I watched [a fireship short](https://www.youtube.com/watch?v=ITogH7lJTyE) and ended up in a rabbit hole to learn how to publish a NPM package. This is still an interesting pattern to use in your codebase but might be best copy pasted instead of being a dependency.
I'll leave the source code here so you don't have to look for the one .ts file in the /src folder:
```TS
export const trytm = async (
promise: Promise,
): Promise<[T, null] | [null, Error]> => {
try {
const data = await promise;
return [data, null];
} catch (throwable) {
if (throwable instanceof Error) return [null, throwable];
throw throwable;
}
};
```
## Attributions
This code is blatantly stolen from [a fireship youtube short](https://www.youtube.com/watch?v=ITogH7lJTyE), with minor additions to make `data` infer its typing from the promise passed as an argument.