Quantcast
Channel: ReScript Forum - Latest posts
Viewing all articles
Browse latest Browse all 2592

How to compose async results?

$
0
0

Not sure I’m completely answering the question here, but lately I’ve been using a pretty light weight pipeable pattern using polyvariants to accumulate errors. A superficial example:

type parsed = {content: string}

let parse = async s => {
  switch s {
  | "hello" => Ok({content: "hello"})
  | _ => Error(#InvalidInput)
  }
}

let transform = async v => {
  switch v {
  | {content: "hello" as s} => Ok(s)
  | _ => Error(#InvalidTransformTarget)
  }
}

let report = async v => {
  switch v {
  | "hello" =>
    Console.log("Yup!")
    Ok("hello")
  | _ => Error(#CannotReport)
  }
}

let consume = v => {
  switch v {
  | "hello" => Ok(#Consumed)
  | "skip" => Ok(#Skipped)
  | _ => Error(#CouldNotConsume)
  }
}

let okThenSync = async (p, fn): result<'v, [> ]> => {
  switch await p {
  | exception e => Error(#UnknownError(e))
  | Ok(v) => fn(v)
  | Error(e) => Error(e)
  }
}

let okThen = async (p, fn): result<'v, [> ]> => {
  switch await p {
  | exception e => Error(#UnknownError(e))
  | Ok(v) => await fn(v)
  | Error(e) => Error(e)
  }
}

let run = async () => {
  let res =
    parse("test")
    ->okThen(transform)
    ->okThen(report)
    ->okThenSync(consume)

  switch await res {
  | Ok(#Consumed) => Console.log("Consumed!")
  | Ok(#Skipped) => Console.log("Skipped this one")
  | Error(#InvalidInput) => Console.log("Invalid input")
  | Error(#InvalidTransformTarget) => Console.log("Invalid transform target")
  | Error(#CannotReport) => Console.log("Cannot report!")
  | Error(#CouldNotConsume) => Console.log("Could not consume content")
  | Error(#UnknownError(e)) => Console.error2("Exception!", e)
  }
}

Playground link.

It’s small and malleable enough that you can just turn it into whatever you need, add helpers as you go, etc.

EDIT: Added general error handling as well.


Viewing all articles
Browse latest Browse all 2592

Trending Articles