napi-rs Docs

Reference

Reference

Ref is very similar to Rc in Rust. But it will not decrease the ref count when dropped, you need to call the unref method on it manually.

In some scenarios, you may need to manually extend the lifetime of certain JavaScript objects to prevent them from being reclaimed by the GC prematurely. Unlike using objects in JavaScript, keeping a reference or value of a JsObject in Rust is opaque to the Node.js GC system, meaning that the GC doesn't know that you still have an Object value that you want to use at some point in the future. GC will ruthlessly recycle it when it sees fit. At this point we need to create a Reference for this object, which is equivalent to telling the Node.js GC system: hey I still need this object, don't recycle it yet.

We usually need to manually extend the lifetime of an Object when doing some asynchronous operations, such as storing the value of some object in Task or ThreadSafeFunction. These objects can't be destroyed after the function finishes executing, so we need to wait until the asynchronous task finishes executing and then manually call the unref method to tell the GC that we don't need the object anymore.

struct Hash(Ref<JsBufferValue>);
impl Task for Hash {
type Output = String;
type JsValue = JsString;
fn compute(&mut self) -> Result<Self::Output> {
Ok(base64(&self.0))
}
fn resolve(self, env: Env, output: Self::Output) -> Result<Self::JsValue> {
let result = env.create_string_from_std(output);
self.0.unref(env)?;
result
}
}
#[js_function(1)]
// return Promise Object
fn async_hash(ctx: CallContext) -> Result<JsObject> {
let input_data = ctx.get::<JsBuffer>(0)?.into_ref()?;
let hash = Hash(input_data);
ctx.env.spawn(hash).map(|async_task| async_task.promise_object())
}
fn base64(data: &[u8]) -> String {
todo!();
}
asyncHash(Buffer::from([1, 2])).then((result) => {
console.log(result) // 0102
})
Edit this page on GitHub