summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/js/asyncjs.nim69
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`)"