summaryrefslogtreecommitdiff
path: root/viz.js/promise/promise.ml
blob: f9f7e5357f8bc2cc70100539d8861aed65d8053a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
open Js_of_ocaml

type ('a, 'b) promise

type 'a resolve = 'a -> unit

type 'a reject = 'a -> unit

let promise_global = Js.Unsafe.global##._Promise

let is_supported () = Js.Optdef.test promise_global

let make f =
  Js.Unsafe.new_obj promise_global [|Js.Unsafe.inject f|]

let resolve value =
  Js.Unsafe.fun_call promise_global##.resolve [|Js.Unsafe.inject value|]

let reject value =
  Js.Unsafe.fun_call promise_global##.reject [|Js.Unsafe.inject value|]

let js_of_opt = function
  | Some value -> Js.Unsafe.inject value
  | None       -> Js.Unsafe.inject Js.undefined

let then_bind ~on_fulfilled ?on_rejected promise =
  Js.Unsafe.meth_call promise "then"
    [|Js.Unsafe.inject on_fulfilled; js_of_opt on_rejected|]

let then_map ~on_fulfilled ?on_rejected promise =
  Js.Unsafe.meth_call promise "then"
    [|Js.Unsafe.inject on_fulfilled; js_of_opt on_rejected|]

let catch_bind ~on_rejected promise =
  Js.Unsafe.meth_call promise "catch" [|Js.Unsafe.inject on_rejected|]

let catch_map ~on_rejected promise =
  Js.Unsafe.meth_call promise "catch" [|Js.Unsafe.inject on_rejected|]

let then_final ~on_fulfilled ~on_rejected promise =
  Js.Unsafe.meth_call promise "then"
    [|Js.Unsafe.inject on_fulfilled; Js.Unsafe.inject on_rejected|]

let all promises =
  let intermediate_promise =
    Js.Unsafe.fun_call promise_global##.all
      [|Js.Unsafe.inject (Js.array promises)|]
  in
  then_map
    ~on_fulfilled:(fun js_array -> Js.to_array js_array) intermediate_promise

let race promises =
  Js.Unsafe.fun_call promise_global##.race
    [|Js.Unsafe.inject (Js.array promises)|]

module Infix = struct
  let (>>=) promise on_fulfilled = then_bind ~on_fulfilled promise
  let (>|=) promise on_fulfilled = then_map  ~on_fulfilled promise

  let (>>~) promise on_rejected = catch_bind ~on_rejected promise
  let (>|~) promise on_rejected = catch_map  ~on_rejected promise

  let (>||) promise (on_fulfilled, on_rejected) =
    then_final ~on_fulfilled ~on_rejected promise
end