diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/js/asyncjs.nim | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/lib/js/asyncjs.nim b/lib/js/asyncjs.nim index 76b948e6a..45053fbaa 100644 --- a/lib/js/asyncjs.nim +++ b/lib/js/asyncjs.nim @@ -57,12 +57,13 @@ ## If you need to use this module with older versions of JavaScript, you can ## use a tool that backports the resulting JavaScript code, as babel. -import std/jsffi -import std/macros - when not defined(js) and not defined(nimsuggest): {.fatal: "Module asyncjs is designed to be used with the JavaScript backend.".} +import std/jsffi +import std/macros +import std/private/since + type Future*[T] = ref object future*: T @@ -154,3 +155,65 @@ proc newPromise*[T](handler: proc(resolve: proc(response: T))): Future[T] {.impo proc newPromise*(handler: proc(resolve: proc())): Future[void] {.importcpp: "(new Promise(#))".} ## A helper for wrapping callback-based functions ## into promises and async procedures. + +when defined(nimExperimentalAsyncjsThen): + since (1, 5, 1): + #[ + TODO: + * map `Promise.all()` + * proc toString*(a: Error): cstring {.importjs: "#.toString()".} + + Note: + We probably can't have a `waitFor` in js in browser (single threaded), but maybe it would be possible + in in nodejs, see https://nodejs.org/api/child_process.html#child_process_child_process_execsync_command_options + and https://stackoverflow.com/questions/61377358/javascript-wait-for-async-call-to-finish-before-returning-from-function-witho + ]# + + type Error* {.importjs: "Error".} = ref object of JsRoot + ## https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error + message*: cstring + name*: cstring + + type OnReject* = proc(reason: Error) + + proc then*[T, T2](future: Future[T], onSuccess: proc(value: T): T2, onReject: OnReject = nil): Future[T2] = + ## See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then + asm "`result` = `future`.then(`onSuccess`, `onReject`)" + + proc then*[T](future: Future[T], onSuccess: proc(value: T), onReject: OnReject = nil): Future[void] = + ## See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then + asm "`result` = `future`.then(`onSuccess`, `onReject`)" + + proc then*(future: Future[void], onSuccess: proc(), onReject: OnReject = nil): Future[void] = + ## See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then + asm "`result` = `future`.then(`onSuccess`, `onReject`)" + + proc then*[T2](future: Future[void], onSuccess: proc(): T2, onReject: OnReject = nil): Future[T2] = + ## See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then + asm "`result` = `future`.then(`onSuccess`, `onReject`)" + + proc catch*[T](future: Future[T], onReject: OnReject): Future[void] = + ## See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch + runnableExamples: + from std/sugar import `=>` + from std/strutils import contains + proc fn(n: int): Future[int] {.async.} = + if n >= 7: raise newException(ValueError, "foobar: " & $n) + else: result = n * 2 + proc main() {.async.} = + let x1 = await fn(3) + assert x1 == 3*2 + let x2 = await fn(4) + .then((a: int) => a.float) + .then((a: float) => $a) + assert x2 == "8.0" + + var reason: Error + await fn(6).catch((r: Error) => (reason = r)) + assert reason == nil + await fn(7).catch((r: Error) => (reason = r)) + assert reason != nil + assert "foobar: 7" in $reason.message + discard main() + + asm "`result` = `future`.catch(`onReject`)" |