Saltar al contenido

Async / Await y Fetch

En esta página

async fn es azúcar para fn*: llamar a una función asíncrona agenda su cuerpo en el planificador cooperativo y devuelve inmediatamente un Future<T>. await suspende al llamador hasta que el Future sea resuelto.

En el nivel superior del programa, await llama internamente a block_on y dirige el planificador de forma síncrona — por lo que puedes usar await directamente en el nivel del módulo.

Await secuencial, Promise.all para paralelismo, Promise.race, Promise.any y cancelación de Future.

03-async-await.zolo
Playground
// Feature: TypeScript-style async/await

// Syntax:

//   async fn name() -> T { ... return T }

//   let fut = name()         // returns a Future<T>, body spawned

//   let v = await fut         // parks until fut settles, returns T

//

// Calling an `async fn` schedules its body on the cooperative

// scheduler and returns a Future immediately. `await` parks the

// caller until the Future settles. Top-level `await` falls back to

// `block_on(fut)` and drives the scheduler synchronously.

//

// For lazy producer/iterator semantics use `fn*` (generator) instead.

// `async fn` is for tasks: I/O simulation, parallel work, fan-out/in.


use std::async::Promise

async fn fetch(url: str) -> str {
  sleep 30ms
  return "GET {url} -> 200 OK"
}

// Sequential await — feels like synchronous code:

print("=== sequential")
let r1 = await fetch("/a")
let r2 = await fetch("/b")
print(r1)
print(r2)

// Parallel via Promise.all — both bodies run concurrently:

print("=== parallel via Promise.all")
let pages = await Promise.all([
  fetch("/x"),
  fetch("/y"),
  fetch("/z"),
])
print("len: {pages.len()}")
print(pages[0])
print(pages[1])
print(pages[2])

// Promise.race — first to settle wins:

async fn slow_response() -> str {
  sleep 100ms
  return "slow"
}
async fn fast_response() -> str {
  sleep 20ms
  return "fast"
}
print("=== Promise.race")
let winner = await Promise.race([slow_response(), fast_response()])
print("winner: {winner}")

// Promise.any — first fulfillment wins (rejections are tolerated

// unless every input rejects).

async fn might_fail(label: str, succeed: bool) -> str {
  sleep 25ms
  if !succeed { panic("rejected: {label}") }
  return label
}
print("=== Promise.any (some reject)")
let first = await Promise.any([
  might_fail("a", false),
  might_fail("b", true),
  might_fail("c", false),
])
print("first ok: {first}")

// Cancellation — `fut.cancel()` settles the Future to "cancelled".

// Awaiters see a rejection; cooperative bodies can register cleanup

// via `fut.on_cancel(cb)` when they want it.

print("=== cancellation")
let f = slow_response()
f.cancel()
print("done after cancel: {f.is_done()}")

// Promise.resolve / Promise.reject — wrap synchronous values:

print("=== Promise.resolve / .reject")
let imm = await Promise.resolve("hello")
print("immediate: {imm}")

Para comunicación con servidores HTTP, Zolo ofrece la API fetch al estilo Node.js. El retorno es un Future<Response>; el cuerpo puede leerse con .text(), .json() o .bytes() — todos asíncronos.

GET simple, POST con JSON, fan-out paralelo via Promise.all y cancelación via AbortController.

04-fetch.zolo
Playground
// Feature: Node.js-style fetch

//

// `fetch(url, options?)` returns a Future<Response>. Use `await` to

// settle it. Response carries `.status`, `.ok`, `.headers` (case-

// insensitive) and async body readers `.text()`, `.json()`, `.bytes()`.

//

// HTTPS works via rustls. No HTTPS-specific configuration needed.


use std::json
use std::async::Promise

// ── Simple GET ────────────────────────────────────────────────────

print("=== GET")
let res = await fetch("http://httpbin.org/get")
print("status: {res.status}")
print("ok:     {res.ok}")
let ctype = res.headers.get("content-type")
print("ctype:  {ctype}")
let body = await res.text()
print("body length: {body.len()}")

// ── POST with JSON body ───────────────────────────────────────────

print("=== POST JSON")
let post = await fetch("http://httpbin.org/post", #{
    method: "POST",
    headers: #{"Content-Type": "application/json"},
    body: json.encode(#{name: "alice", age: 30}),
})
let data = await post.json()
print("server saw: {data.json.name}")

// ── Parallel fan-out via Promise.all ──────────────────────────────

print("=== parallel")
let pages = await Promise.all([
    fetch("http://httpbin.org/delay/1"),
    fetch("http://httpbin.org/delay/1"),
    fetch("http://httpbin.org/delay/1"),
])
print("got {pages.len()} responses concurrently")

// ── Cancellation via AbortController ──────────────────────────────

print("=== abort")
let ctrl = AbortController.new()
let p = fetch("http://httpbin.org/delay/10", #{signal: ctrl.signal})
setTimeout(|| { ctrl.abort() }, 100)
let ok, err = pcall(|| { await p })
print("aborted: ok={ok} err={err}")

Consejo: usa async fn cuando la semántica es la de una tarea (I/O, trabajo paralelo, fan-out). Para secuencias lazy prefiere fn* (generador).

Buscar en Zolo

9 resultados

enespt-br