LEVIATHAN v962456e · 962456eee1

Standard Library

class Promise<T>

A value that arrives later.

since 0.1.0-alpha.1linuxwindows

Overview

A promise starts out pending and is settled once by resolve. await promise waits, without blocking the rest of the program, until the promise is ready and then gives its value; if the promise is already ready, await returns at once. Any function may await, because there is no separate async function type: a function that returns a Promise<T> is simply the asynchronous form. A promise that only signals completion is a Promise<void>, resolved with resolve(None).

Create a pending promise with Promise() and a ready one with Promise(value). Something else, usually a timer or a callback, calls resolve when the value exists.

Description

Promise<T> is an ordinary class. The language gives it no special rules and wraps nothing for you: a function that is meant to produce a value later must return a real Promise, and the body of such a function is responsible for resolving it. await is the one operation the language treats specially, and it only needs something promise-shaped to wait on.

A promise is created in one of two states.

  • Promise() is pending: it holds no value yet. isReady() is false.
  • Promise(v) is pre-resolved: it already holds v. isReady() is true.

resolve(v) stores a value and marks the promise ready. get() reads the stored value, and then(cb) registers a callback to run with the value. If the promise is already ready, then runs the callback immediately; otherwise the callback runs inside the call to resolve that settles the promise.

Pending and pre-resolved promises

Promise<int> ready = Promise(42);
console.writeln(ready.isReady());
console.writeln(ready.get());

Promise<string> later = Promise();
console.writeln(later.isReady());
later.then((s) => console.writeln("then saw ${s}"));
console.writeln("resolving");
later.resolve("hello");
console.writeln(later.isReady());
true
42
false
resolving
then saw hello
true

A promise whose only job is to say "this has finished" is a Promise<void>. Resolve it with the unit value, None: done.resolve(None). A pre-resolved completion promise is Promise(None). Awaiting a Promise<void> waits but yields no usable value.

Rules

  • A function that returns a promise must return a real Promise; there is no implicit wrapping of plain values and no async keyword.
  • await expr unwraps a Promise<T> to a T. An await on a promise that is already ready does not suspend at all. See lang.await for what runs while an await waits.
  • then holds one callback. Calling then on a pending promise a second time replaces the first callback instead of adding to it.
  • Resolve a promise once. Resolving again is not an error, but it overwrites the stored value (and runs a pending then callback again), so treat a second resolve as a bug.
  • then runs its callback synchronously, in the context of whoever resolves the promise. If you need to wait in straight-line code, use await.

Examples

A function that returns a promise, resolved by a timer and consumed with await:

Awaiting a promise resolved by a timer

Promise<int> square(int n) {
    Promise<int> p = Promise();
    std::sysTimerStart(5, 0, (t) => p.resolve(n * n));
    return p;
}
int sq = await square(7);
console.writeln("7 squared is ${sq}");

Promise<int> already = Promise(9);
console.writeln(await already);
console.writeln(await 5);
7 squared is 49
9
5

The last line shows that await on a value that is not a promise yields the value unchanged.

Notes

A Worker<T>, the handle returned by std::spawn, is itself a Promise<T>, so joining a worker is just an await.

Examples

Waiting for a value that a timer provides

Promise<int> done = Promise();
done.then((v) => { console.writeln("then saw ${v}"); });
console.writeln("ready? ${done.isReady()}");
done.resolve(7);
console.writeln("ready? ${done.isReady()}");
Promise<int> later = Promise();
std::sysTimerStart(10, 0, (n) => { later.resolve(99); });
int v = await later;
console.writeln("awaited ${v}");
ready? false
then saw 7
ready? true
awaited 99

Constructors

new

new()

Create a pending promise.

The promise is not ready until something calls resolve on it.

Examples

Pending and already-resolved promises

Promise<int> pending = Promise();
console.writeln(pending.isReady());
Promise<int> done = Promise(5);
console.writeln(done.isReady());
console.writeln(done.get());
false
true
5
new(T v)

Create a promise that is already resolved with a value.

Awaiting it returns the value at once, and then runs its callback immediately.

Parameters

v
The value the promise holds.

Fields

ready

bool ready

Whether the promise has been settled. Prefer isReady.

value

T value

The settled value; meaningful only once the promise is ready. Prefer get or await.

Methods

get

get() -> T

Read the promise's value without waiting.

The value is only meaningful after the promise is ready; check isReady first, or use await to wait for it.

Returns

The settled value.

Examples

Promise<int> p = Promise(42);
if (p.isReady()) {
    console.writeln(p.get());
}
42

isReady

isReady() -> bool

Tell whether the promise has been settled.

Returns

true once the promise has been resolved, otherwise false.

Examples

Promise<int> p = Promise();
console.writeln(p.isReady());
p.resolve(1);
console.writeln(p.isReady());
false
true

resolve

resolve(T v) -> void

Settle the promise with a value.

The promise becomes ready, anything awaiting it wakes up, and the callback given to then runs with the value. For a Promise<void> resolve with None.

Parameters

v
The value to settle the promise with.

Examples

Promise<string> p = Promise();
p.then((s) => { console.writeln("got ${s}"); });
p.resolve("hello");
console.writeln(p.get());
Promise<void> signal = Promise();
signal.resolve(None);
console.writeln(signal.isReady());
got hello
hello
true

then

then((T) => void cb) -> void

Run a callback with the value once the promise is ready.

If the promise is already ready the callback runs immediately. Otherwise it runs inside resolve, in the context of whoever resolves the promise. A promise keeps only one callback: registering a second one before the promise is resolved replaces the first.

Parameters

cb
The function to call with the value.

Examples

Promise<int> p = Promise();
p.then((v) => { console.writeln("first ${v}"); });
p.then((v) => { console.writeln("second ${v}"); });
p.resolve(1);
p.then((v) => { console.writeln("late ${v}"); });
second 1
late 1

See also

  • Worker — The handle to a value that another worker is computing.
  • awaitTimeout — Wait for a promise, but give up after a time limit.
  • Timer — A source of ticks on the event loop.
  • InStream — The reading end of a stream: a queue of values of type T that something else produces.