Reference · Browser
parallel
parallel(any...) -> listWhat it does
Calls several functions at once and gives their results as a list, in the order the
functions were given. Their waits overlap: database calls, http.* and sleep on the
server, server fn calls in the browser (where it is Promise.all). Their computing
does not, since Quillo code runs one piece at a time, so parallel shortens waiting,
not arithmetic. The functions may be given one by one or as one list.
Examples
fn slow(v) { sleep(100); v }let t = now()let [a, b, c] = parallel(() => slow(1), () => slow(2), () => slow(3))print(a, b, c, now() - t < 250)print(parallel([() => "x", () => "y"]))1 2 3 true["x", "y"]server fn load_user(id: int) = db.one("select * from users where id = ?", id)server fn load_orders(id: int) = db.query("select * from orders where user_id = ?", id)component Account(id: int) { state data = parallel(() => load_user(id), () => load_orders(id)) // one round trip's wait let [user, orders] = data <div> <h2>{user.name}</h2> <button @click={() => { data = parallel(() => load_user(id), () => load_orders(id)) }}>Refresh</button> <ul>{for o in orders => <li key={o.id}>{o.total}</li>}</ul> </div>}Edge cases
- Results come back in the order given, whichever finished first.
- An error value a function returns, or passes on with
?, is its result like any other, and stops nothing. A runtime error in one function stops the others on the server at their next step (a call, a loop's round, a builtin, asleep, which ends at once), aparallelinside them too, and the call fails with that error. What they did before the stop stays done (a row written is written). set_cookie,set_session,end_session,session()andpublishwork inside the functions, and what they set is merged into the request in the functions' order; a write is seen by the reads after it, as outside. A function that reads the visitor (session(), a cookie) makes the answer the visitor's own, as anywhere.- No functions gives
[]. - Inside
db.transactionthe functions run one after another, so their SQL is part of the transaction. - In a component it may be called from an event handler or as a
stateinitializer (on the server while rendering, in the browser on navigation). In aletof the component it is refused when the program loads:`parallel` waits on the server, so a component can only call it from an event handler (@click={() => { ... }}) or to set state: state x = parallel(...). quillo checkdoes not look at the arguments (any...): a value that is not a function is found when the call runs.
print(parallel(() => 1, () => "two"))print(parallel(() => { sleep(50); "slow" }, () => "fast"))print(parallel(() => err("boom"), () => int("x")?, () => 3))print(parallel())[1, "two"]["slow", "fast"][err("boom"), err("not an int: \"x\""), 3][]Errors
An argument that is not a function is a runtime error, not an error value, with the argument's number. A function that fails with a runtime error fails the call with that error, after stopping the others.
print(parallel(1, () => 2))line 1: `parallel` takes functions to call, like parallel(() => a(), () => b()); argument 1 is intprint(parallel(() => 1, () => upper(42)))line 1: `upper` expects a str as argument 1, got int in a function, called at main.qwe:1Chaining
A list of functions pipes in as the one argument, and the result is a list:
let jobs = [1, 2, 3] | map((n) => () => n * 10)print(jobs | parallel | sum)let [first, second] = parallel(() => "a", () => "b")print(first + second)60abSee also
sleep, live, idempotent, http.get
Thread 0 posts
On parallel(): questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.
Edit this page on GitHub · every example's output was made by running it (tools/refcheck.mjs) · questions on Discord or r/quillo