node-addon-api
node-addon-api copied to clipboard
AsyncWorker pass Napi::Object problem?
I want to pass in the object as a parameter
I get error
"Fatal error in HandleScope::HandleScope" "Entering the V8 API without proper locking in place"
example
class TestWorker : public Napi::AsyncWorker {
public:
TestWorker(Napi::Function& callback, Napi::Object& object)
: Napi::AsyncWorker(callback), object(object) {}
~TestWorker() {}
void Execute() {
Napi::TypedArray typedArray = object.Get("data").As<Napi::TypedArray>();
Napi::Uint8Array uint8Array = typedArray.As<Napi::Uint8Array>();
std::vector<uchar> vector(uint8Array.Data(), uint8Array.Data() + uint8Array.ElementLength());
// vector data send to other function calculator
uint32_t width = object.Get("width").As<Napi::Number>().Uint32Value();
uint32_t height = object.Get("height").As<Napi::Number>().Uint32Value();
size = width * height;
result.Set("size", size);
std::cout << size << std::endl;
}
void OnOK() { Callback().Call({Env().Undefined(), result}); }
Napi::Object object;
Napi::Object result = Napi::Object::New(Env());
uint32_t size;
};
Napi::Value TestAsync(const Napi::CallbackInfo& info) {
Napi::Object object = info[0].As<Napi::Object>();
Napi::Function callback = info[1].As<Napi::Function>();
TestWorker* testWorker = new TestWorker(callback, object);
testWorker->Queue();
return info.Env().Undefined();
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "testAsync"),Napi::Function::New(env, TestAsync));
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
const object = { data: new Uint8Array([1, 2, 3, 4, 5, 6]), width: 123, height: 456 };
addon.testAsync(object, (err, result) => {
console.log(result);
});
/*
Error message
# Fatal error in HandleScope::HandleScope
# Entering the V8 API without proper locking in place
*/
Hi @tak40548798 ,
Please check the documentation for the Execute callback, specifically:
As the method is not running on the main event loop, it must avoid calling any methods from node-addon-api or running any code that might invoke JavaScript. Instead, once this method is complete any interaction through node-addon-api with JavaScript should be implemented in the Napi::AsyncWorker::OnOK method and Napi::AsyncWorker::OnError which run on the main thread and are invoked when the Napi::AsyncWorker::Execute method completes.
You cannot execute JavaScript code in the Execute
callback.
Let us know if you need any additional assistance.
Thanks, Kevin
Hi @tak40548798,
@KevinEady is right you cannot execute JavaScript code in the Execute
method so one idea is to refactor your code like reported below:
#include <napi.h>
class TestWorker : public Napi::AsyncWorker {
public:
TestWorker(Napi::Function& callback, Napi::Object& object)
: Napi::AsyncWorker(callback) {
Napi::TypedArray typedArray = object.Get("data").As<Napi::TypedArray>();
Napi::Uint8Array uint8Array = typedArray.As<Napi::Uint8Array>();
vector = std::vector<char>(uint8Array.Data(), uint8Array.Data() + uint8Array.ElementLength());
// vector data send to other function calculator
width = object.Get("width").As<Napi::Number>().Uint32Value();
height = object.Get("height").As<Napi::Number>().Uint32Value();
}
~TestWorker() {}
void Execute() {
result = width * height;
}
void OnOK() {
Napi::Object obj = Napi::Object::New(Env());
obj["size"] = result;
Callback().Call({Env().Undefined(), obj});
}
std::vector<char> vector;
uint32_t width;
uint32_t height;
uint32_t result;
};
Napi::Value TestAsync(const Napi::CallbackInfo& info) {
Napi::Object object = info[0].As<Napi::Object>();
Napi::Function callback = info[1].As<Napi::Function>();
TestWorker* testWorker = new TestWorker(callback, object);
testWorker->Queue();
return info.Env().Undefined();
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "testAsync"),Napi::Function::New(env, TestAsync));
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
'use strict'
const addon = require('bindings')('addon')
const object = { data: new Uint8Array([1, 2, 3, 4, 5, 6]), width: 123, height: 456 };
addon.testAsync(object, (err, result) => {
console.log(result);
});
Let us know if this help you or need some other assistance.
Is is possible to return an ObjectWrap as the result of a Promise? Seems impossible given CallbackInfo isn't accessible within OnOK().
This issue is stale because it has been open many days with no activity. It will be closed soon unless the stale label is removed or a comment is made.