Skip to content

Latest commit

 

History

History

tokio-fetch

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

tokio-fetch

Example of spawning a Rust async task on the tokio thread pool and resolving a JavaScript Promise after it completes.

Note: This example uses a pre-release version of Neon.

Methods

function nodeReleaseDate(): Promise<string>

Asynchronously fetch the release date for the currently running Node process from nodejs.org.

Design

Executor

For optimum task scheduling, it is best to have a single Rust task executor (e.g., tokio runtime). To make the runtime singleton available to Neon functions, it is stored in a global using OnceCell.

use once_cell::sync::OnceCell;
use tokio::runtime::Runtime;

static RUNTIME: OnceCell<Runtime> = OnceCell::new();

A small helper is provided to lazily initialize the runtime and throw an exception on failure.

fn runtime<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static Runtime> {
    RUNTIME.get_or_try_init(|| Runtime::new().or_else(|err| cx.throw_error(err.to_string())))
}

Spawning Tasks

Tasks may be spawned on the tokio runtime by using the RUNTIME handle. Spawning a task does not block the current thread. Inside a task the await keyword may be used and typical async Rust patterns may be used.

let rt = runtime(&mut cx)?;

rt.spawn(async move {
    // Asynchronous Rust may used in here
});

Promises

When a task is spawned on the tokio runtime, it will be executed at a later time. JavaScript needs to be notified when the task completes.

let channel = cx.channel();
let (deferred, promise) = cx.promise();

rt.spawn(async move {
    // Code here executes non-blocking on the tokio thread pool

    deferred.settle_with(&channel, move |mut cx| {
        // Code here executes blocking on the JavaScript main thread

        Ok(cx.undefined())
    });
});

Ok(promise)