/
Relude_Js_Promise.re
104 lines (92 loc) · 2.79 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
/**
# Relude.Js.Promise
Utilities for interoperating with `Js.Promise`
*/
/**
Lifts a `Js.Promise` into a `Relude.IO`
Note: prefer `toIOLazy` over this function if possible. `Js.Promise`s are 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 => {
onDone(Belt.Result.Ok(v));
promise;
})
|> Js.Promise.catch(e => {
onDone(Belt.Result.Error(e));
promise;
})
|> 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 => {
onDone(Belt.Result.Ok(v));
promise;
})
|> Js.Promise.catch(e => {
onDone(Belt.Result.Error(e));
promise;
})
|> 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 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) {
| Belt.Result.Ok(v) => resolve(. v)
| Belt.Result.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) {
| Belt.Result.Ok(v) => resolve(. v)
| Belt.Result.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) {
| Belt.Result.Ok(v) => resolve(. v)
| Belt.Result.Error(e) => reject(. Relude_Js_Exn.unsafeToExn(e))
}
)
);