mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-20 14:25:23 +00:00
asyncjs: add then, catch for promise pipelining (#16871)
* asyncjs: add then * improve tests, changelog, API * fix cryptic windows error: The parameter is incorrect * address comments
This commit is contained in:
@@ -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`)"
|
||||
|
||||
Reference in New Issue
Block a user