Skip to content

Commit

Permalink
implement promise start (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
CrowdHailer authored Sep 30, 2024
1 parent 1897f04 commit 10f1902
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Add `start` to the `promise` module.
- Add `wait` to `promise` module.

## v0.12.0 - 2024-08-19
Expand Down
9 changes: 9 additions & 0 deletions src/gleam/javascript/promise.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ pub type Promise(value)
@external(javascript, "../../gleam_javascript_ffi.mjs", "newPromise")
pub fn new(a: fn(fn(value) -> Nil) -> Nil) -> Promise(value)

/// Create a new promise and resolve function. The first time the resolve function
/// is called the promise resolves with that value.
///
/// This function is useful in cases where a reference to the promise and resolver
/// are needed.
///
@external(javascript, "../../gleam_javascript_ffi.mjs", "start_promise")
pub fn start() -> #(Promise(a), fn(a) -> Nil)

/// Create a promise that resolves immediately.
///
@external(javascript, "../../gleam_javascript_ffi.mjs", "resolve")
Expand Down
8 changes: 8 additions & 0 deletions src/gleam_javascript_ffi.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ export function newPromise(executor) {
);
}

export function start_promise() {
let resolve;
const promise = new Promise((r) => {
resolve = (value) => {r(PromiseLayer.wrap(value))}
})
return [promise, resolve]
}

export function resolve(value) {
return Promise.resolve(PromiseLayer.wrap(value));
}
Expand Down
19 changes: 19 additions & 0 deletions test/gleam/javascript/promise_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,25 @@ pub fn new_does_not_collapse_nested_promise_test() {
})
}

pub fn start_promise_test() {
let #(p, resolve) = promise.start()
promise.tap(p, fn(value) {
let assert 1 = value
})
resolve(1)
}

pub fn start_does_not_collapse_nested_promise_test() {
let #(p, resolve) = promise.start()
promise.tap(p, 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`.
let assert ObjectType = javascript.type_of(value)
})
resolve(promise.resolve(1))
}

pub fn map_does_not_collapse_nested_promise_test() -> Promise(Promise(Int)) {
promise.resolve(1)
|> promise.map(promise.resolve)
Expand Down

0 comments on commit 10f1902

Please sign in to comment.