diff options
author | Louis Pilfold <louis@lpil.uk> | 2021-08-29 17:18:37 +0100 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2021-08-29 17:18:37 +0100 |
commit | c2d25106df806fd9de96f1ab3186102ba27dceab (patch) | |
tree | 833f17fd6e3821f6ee2d536ecdef96cc3418d944 | |
parent | 08bf033063a8d3ce789939bac36ed39fc6bc2eca (diff) | |
download | javascript-c2d25106df806fd9de96f1ab3186102ba27dceab.tar.gz javascript-c2d25106df806fd9de96f1ab3186102ba27dceab.zip |
Promises
-rw-r--r-- | CHANGELOG.md | 6 | ||||
-rw-r--r-- | src/ffi.js | 30 | ||||
-rw-r--r-- | src/gleam/javascript/promise.gleam | 11 | ||||
-rw-r--r-- | test/gleam/javascript/promise_test.gleam | 20 |
4 files changed, 65 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index fe8e251..556e284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,10 @@ ## Unreleased +- The `javascript` module was created with the `TypeOf`, and `Symbol` types, and + `find_symbol`, and `type_of` functions. - The `javascript/array` module was created with the `Array(element)` type and `to_list`, `from_list`, `map`, `fold`, `fold_right`, `get`, and `length` functions. -- The `javascript` module was created with the `TypeOf`, and `Symbol` types, and - `find_symbol`, and `type_of` functions. +- The `javascript/promise` module was created with the `Promise(value)` type and + `resolve`, `map`, and `then` functions. @@ -64,3 +64,33 @@ export function type_of(value) { export function get_symbol(name) { return Symbol.for(name); } + +// A wrapper around a promise to prevent `Promise<Promise<T>>` collapsing into +// `Promise<T>`. +class PromiseLayer { + constructor(promise) { + this.promise = promise; + } + + static wrap(value) { + return value instanceof Promise ? new PromiseLayer(value) : value; + } + + static unwrap(value) { + return value instanceof PromiseLayer ? value.promise : value; + } +} + +export function resolve(value) { + return Promise.resolve(PromiseLayer.wrap(value)); +} + +export function then(promise, fn) { + return promise.then((value) => fn(PromiseLayer.unwrap(value))); +} + +export function map_promise(promise, fn) { + return promise.then((value) => + PromiseLayer.wrap(fn(PromiseLayer.unwrap(value))) + ); +} diff --git a/src/gleam/javascript/promise.gleam b/src/gleam/javascript/promise.gleam new file mode 100644 index 0000000..4f8d54c --- /dev/null +++ b/src/gleam/javascript/promise.gleam @@ -0,0 +1,11 @@ +// TODO: docs +pub external type Promise(value) + +pub external fn resolve(value) -> Promise(value) = + "../../ffi.js" "resolve" + +pub external fn then(Promise(a), fn(a) -> Promise(b)) -> Promise(b) = + "../../ffi.js" "then" + +pub external fn map(Promise(a), fn(a) -> b) -> Promise(b) = + "../../ffi.js" "map_promise" diff --git a/test/gleam/javascript/promise_test.gleam b/test/gleam/javascript/promise_test.gleam new file mode 100644 index 0000000..876aefb --- /dev/null +++ b/test/gleam/javascript/promise_test.gleam @@ -0,0 +1,20 @@ +import gleam/javascript/promise.{Promise} +import gleam/javascript.{ObjectType} + +pub fn map_does_not_collapse_nested_promise_test() -> Promise(Promise(Int)) { + promise.resolve(1) + |> promise.map(promise.resolve) + |> promise.map(fn(value) { + // If the `Promise(Promise(Int))` collapsed into `Promise(Int)` (as they + // do for normal JS promises) then this would fail as the value would be the + // int value `1`. + assert ObjectType = javascript.type_of(value) + value + }) +} + +pub fn then_does_collapse_nested_promise_test() -> Promise(Int) { + promise.resolve(1) + |> promise.then(promise.resolve) + |> promise.map(fn(value) { assert 1 = value }) +} |