triston-notes/Cards/dev/Js promise handeler.md
2023-10-21 18:52:54 -05:00

2.4 KiB

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:

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:

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:

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:

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

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

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

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