Nyx compiled to wasm32-wasi can use real await: an async fn that calls await browser_fetch_await(...) WAITS for the server's response and continues on the next line with the value, without splitting the flow into a closure per request. The new std/browser_await module lives apart from std/browser on purpose: only a program that imports it pays for Asyncify (and binaryen as a build dependency).
// 109 — await en el navegador: una pantalla que carga una factura sin callbacks // // Target wasm32-wasi (corre en el navegador, o bajo node con // examples/browser/run-node.mjs). `await browser_fetch_await(...)` ESPERA la // respuesta del servidor y la función sigue en la línea siguiente con el // valor: sin partir el flujo en un cierre por cada pedido. // // Construir: nyx build --target wasm32-wasi // (necesita binaryen: `sudo apt install binaryen`, o NYX_WASM_OPT=/ruta/a/wasm-opt; // nyx build lo usa SOLO porque el programa espera al anfitrión) // // Lo que conviene saber: // - El status HTTP no es error: un 404 llega como Ok con r.status == 404. // Err es «no hubo respuesta» (kind "connection") o «venció el plazo» ("timeout"). // - UNA sola función puede estar esperando a la vez. Un click que llega // durante el fetch se procesa cuando el fetch termina, en orden. // - spawn y los canales siguen sin existir en wasm: await es secuencial. import "std/browser_await" import "std/dom" import "std/error" async fn cargar_factura(id: int) -> String { let res = await browser_fetch_await_opts("/api/facturas/" + int_to_string(id), "GET", "", 5000) match res { Result.Ok(r) => { if r.status != 200 { return "la factura " + int_to_string(id) + " no está (HTTP " + int_to_string(r.status) + ")" } return r.body } Result.Err(e) => { return "sin respuesta del servidor: " + e.kind + " (" + e.msg + ")" } } } // El botón «abrir» de cada fila llama a este export con el número de factura. #[export_name = "abrir_factura"] fn abrir_factura(id: int) { dom_set_text("#estado", "cargando la factura " + int_to_string(id) + "...") let texto: String = await cargar_factura(id) dom_set_text("#factura", texto) dom_set_text("#estado", "listo") } fn main() { abrir_factura(7) }
#estado → "cargando la factura 7..." #factura → (the response body, or the failure's reason) #estado → "listo"
How it works
The HTTP status is not an error: a 404 arrives as Result.Ok with r.status == 404, and cargar_factura tells them apart by hand. The only thing that lands in Result.Err is getting no response at all — kind "connection" or "timeout", the same Error vocabulary as the rest of the stdlib.
abrir_factura is the export the «open» button of each row calls: it updates the DOM before waiting, waits with await, and updates the DOM again with the result — no callback in between. Only ONE function can be waiting at a time: a click that arrives mid-fetch is processed once the fetch finishes, in order.
Building needs binaryen (wasm-opt) because the generated .ll carries an Asyncify imports marker; a program without #[suspends] compiles byte for byte the same as before. spawn and channels still do not exist in wasm: here await is sequential.