100 lines
2.4 KiB
Markdown
100 lines
2.4 KiB
Markdown
|
---
|
||
|
banner: "https://media.discordapp.net/attachments/1050995657797816341/1091278921972064336/Triston_control_flow_a42cae90-667c-465d-9112-8104d61d0533.png?width=1856&height=1040"
|
||
|
---
|
||
|
up:: [[JavaScript]]
|
||
|
tags::
|
||
|
|
||
|
## The Problem
|
||
|
The Try/Catch flow can get really hairy with multiple requests becoming many lines of logic, like so:
|
||
|
```js
|
||
|
let res1
|
||
|
try{
|
||
|
res1 = await request1()
|
||
|
}catch(e){
|
||
|
// handle some error
|
||
|
}
|
||
|
|
||
|
let res2
|
||
|
try{
|
||
|
res2 = await request2()
|
||
|
}catch(e){
|
||
|
// handle some error
|
||
|
}
|
||
|
|
||
|
let res3
|
||
|
try{
|
||
|
res3 = await request3()
|
||
|
}catch(e){
|
||
|
// handle some error
|
||
|
}
|
||
|
```
|
||
|
|
||
|
As well as the promise chaining can get nasty as well, like so:
|
||
|
```js
|
||
|
request1().then(res => {
|
||
|
requst2().then(res => {
|
||
|
requst3().then(res => {
|
||
|
// do something
|
||
|
}).catch(e => console.error(e))
|
||
|
}).catch(e=>console.error(e))
|
||
|
}).catch(e => console.error(e))
|
||
|
```
|
||
|
|
||
|
#### not ideal.. But theres a solution, that isnt my idea but i wanted to note it
|
||
|
|
||
|
---
|
||
|
## The solution
|
||
|
We can create a single function that acts as a wrapper for the request and return a dictionary of value and error, like so:
|
||
|
```js
|
||
|
export default async function result(cb){
|
||
|
let result = { value: null, error: null };
|
||
|
try {
|
||
|
const r = await cb();
|
||
|
result.value = r;
|
||
|
} catch (error) {
|
||
|
result.error = error;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
and we can now use this function like so:
|
||
|
```js
|
||
|
const {value, error} = await result(request1)
|
||
|
```
|
||
|
|
||
|
we dont need to wrap this in a try/catch because it will not fail
|
||
|
And we can even alias the error and value if needing to make multiple async calls
|
||
|
```js
|
||
|
const {value: aVal, error: aErr} = await result(request1)
|
||
|
const {value: bVal, bErr} = await result(request2)
|
||
|
const {value: cVal, cErr} = await result(request3)
|
||
|
```
|
||
|
|
||
|
Well, what if we need to pass `aVal` to `request2`
|
||
|
EASY
|
||
|
```js
|
||
|
const {value: aVal, error: aErr} = await result(request1)
|
||
|
const {value: bVal, bErr} = await result(async () => await request2(aVal))
|
||
|
const {value: cVal, cErr} = await result(async () => await request3(bVal))
|
||
|
```
|
||
|
|
||
|
And what if we need to control flow, maybe early return?
|
||
|
Again, EASY
|
||
|
```js
|
||
|
const {value: aVal, error: aErr} = await result(request1)
|
||
|
if (aErr) return
|
||
|
|
||
|
const {value: bVal, bErr} = await result(async () => await request2(aVal))
|
||
|
if (!bVal) return
|
||
|
|
||
|
const {value: cVal, cErr} = await result(async () => await request3(bVal))
|
||
|
if (!cErr) return cVal
|
||
|
if (cErr) return "whole thing failed"
|
||
|
```
|
||
|
|
||
|
---
|
||
|
|
||
|
## Types
|
||
|
Maybe we're using typescript and want to make this all type safe, cause right now, we know nothing
|