-
Notifications
You must be signed in to change notification settings - Fork 41
/
Relude_Js_Promise.re
107 lines (98 loc) · 3.1 KB
/
Relude_Js_Promise.re
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
[@ocaml.doc
{|
[Relude.Js.Promise] contains utilities for interoperating with [Js.Promise].
Many of these functions will help you convert to and from [Relude.IO].
|}
]
/**
Lifts a [Js.Promise] into a [Relude.IO]
Note: prefer {!val:toIOLazy} over this function if possible. A [Js.Promise] is
eagerly executed, so using [toIO] with an already-constructed and running
[Js.Promise] will not suspend the side effects.
*/
let toIO: 'a. Js.Promise.t('a) => Relude_IO.t('a, Js.Promise.error) =
promise =>
Relude_IO.async(onDone =>
promise
|> Js.Promise.then_(v => Js.Promise.resolve(onDone(Ok(v))))
|> Js.Promise.catch(e => Js.Promise.resolve(onDone(Error(e))))
|> ignore
);
/**
Lifts a lazily-executed [Js.Promise] into a [Relude.IO].
*/
let toIOLazy:
'a.
(unit => Js.Promise.t('a)) => Relude_IO.t('a, Js.Promise.error)
=
runPromise =>
Relude_IO.async(onDone => {
let promise = runPromise();
promise
|> Js.Promise.then_(v => Js.Promise.resolve(onDone(Ok(v))))
|> Js.Promise.catch(e => Js.Promise.resolve(onDone(Error(e))))
|> ignore;
});
// TODO: not sure how best to handle exn/Js.Exn.t/Js.Promise.error below...
// open to suggestions/ideas
/**
Converts a [Relude.IO] into a [Js.Promise.t]. This function will cause the IO
effects to be run.
The promise that is returned will not reject, it will instead have a [result] as
its resolution.
*/
let fromIOWithResult:
'a 'e.
Relude_IO.t('a, 'e) => Js.Promise.t(result('a, 'e))
=
io =>
Js.Promise.make((~resolve, ~reject as _) =>
io |> Relude_IO.unsafeRunAsync(result => resolve(. result))
);
/**
Converts a [Relude.IO] into a [Js.Promise.t]. This function will cause the IO
effects to be run.
The error channel is unsafely coerced into the promise error type, which is
probably fine, because the [Js.Promise] error type is opaque.
*/
let fromIO: 'a 'e. Relude_IO.t('a, 'e) => Js.Promise.t('a) =
io =>
Js.Promise.make((~resolve, ~reject) =>
io
|> Relude_IO.unsafeRunAsync(result =>
switch (result) {
| Ok(v) => resolve(. v)
| Error(e) => reject(. Relude_Unsafe.coerce(e)) /* TODO: not sure if this is wise/good */
}
)
);
/**
Converts a [Relude.IO] with an extensible OCaml [exn] as the error type into a
[Js.Promise.t]. This function will cause the IO effects to be run.
*/
let fromIOExn: 'a. Relude_IO.t('a, exn) => Js.Promise.t('a) =
io =>
Js.Promise.make((~resolve, ~reject) =>
io
|> Relude_IO.unsafeRunAsync(result =>
switch (result) {
| Ok(v) => resolve(. v)
| Error(e) => reject(. e)
}
)
);
/**
Converts a [Relude.IO] with a [Js.Exn.t] as the error type into a
[Js.Promise.t]. This function will cause the IO effects to be run.
*/
let fromIOJsExn: 'a. Relude_IO.t('a, Js.Exn.t) => Js.Promise.t('a) =
io =>
Js.Promise.make((~resolve, ~reject) =>
io
|> Relude_IO.unsafeRunAsync(result =>
switch (result) {
| Ok(v) => resolve(. v)
| Error(e) => reject(. Relude_Js_Exn.unsafeToExn(e))
}
)
);