I couldn't find in the documentation and examples how to properly handle Object/Buffer/Uint8Array parameters in AsyncWorker?
The task: I'd like to receive data as Uint8Array and use it in AsyncWorker.
If I understand correctly, the data can be garbage collected.
Should I:
ObjectReference and pass it to AsyncWorker constructor?Uint8Array in ObjectReference`?uint8_t* data as something?Naive code:
#include "napi.h"
class DoHeavyMathWorker : public Napi::AsyncWorker {
public:
DoHeavyMathWorker(const Napi::Env& env, uint8_t* data)
: Napi::AsyncWorker{env, "DoHeavyMathWorker"},
m_deferred{env},
m_data{data}
{}
Napi::Promise GetPromise() { return m_deferred.Promise(); }
protected:
void Execute() {
// heavy math with data
if (m_data[0] == 0) {
m_result = 1;
} else {
m_result = 2;
}
}
void OnOK() { m_deferred.Resolve(Napi::Number::New(Env(), m_result)); }
void OnError(const Napi::Error& err) { m_deferred.Reject(err.Value()); }
private:
Napi::Promise::Deferred m_deferred;
uint8_t* m_data;
uint32_t m_result;
};
Napi::Value DoHeavyMath(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (!info[0].IsObject()) {
Napi::TypeError::New(env, "arg must be an object")
.ThrowAsJavaScriptException();
return env.Undefined();
}
Napi::Object obj = info[0].As<Napi::Object>();
uint8_t* data = obj.Get("data").As<Napi::Uint8Array>().Data();
DoHeavyMathWorker* worker = new DoHeavyMathWorker(env, data);
worker->Queue();
return worker->GetPromise();
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set("doHeavyMath", Napi::Function::New(env, DoHeavyMath));
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
JS part:
const result = await addon.doHeavyMath({
data: new Uint8Array([42]),
});
console.log('result:', result);
AsyncWorker docs https://github.com/nodejs/node-addon-api/blob/main/doc/async_worker.mdYou have to create a persistent reference and keep it around for as long as you need the data. Note, that persistent references can only be created and destroyed on the main thread.
You should create it on the heap in the function that creates the AsyncWorker:
auto *persistent = new Napi::ObjectReference(
Napi::Persistent(array_buffer.As<Napi::Object>()));
Pass this reference to the AsyncWorker and delete it in the AsyncWorker callbacks - OnOK and OnError:
// This is everything needed to free the underlying reference
delete persistent;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With