I am not sure how one can call a Node/v8 function within Node's main thread by using event emitting in a separate C++ thread. How is it possible to emit events in a C++ thread?
Before thinking about NanAsyncWorker or uv_queue_work: I don't want to call a C++ function in an Async fashion. I want to do the exact opposite, calling a Javascript function from C++ by emitting events.
EventEmitter() is the constructor function for the EventEmitter object. Since you need to call that constructor with the same this as your new object, you must use either . call() or . apply() with that constructor in order to cause the correct this to be used.
An event emitter is a pattern that listens to a named event, fires a callback, then emits that event with a value. Sometimes this is referred to as a “pub/sub” model, or listener.
The on or addListener method (basically the subscription method) allows you to choose the event to watch for and the callback to be called. The emit method (the publish method), on the other hand, allows you to "emit" an event, which causes all callbacks registered to the event to 'fire', (get called).
Use event emitter if you need to notify the user of a state change. For testing purpose, if you want to make sure a function is called inside a function, emit an event.
You do not need to use uv_queue_work
, but part of LibUV's thread library are the uv_async_*
methods, which are what you'd ideally have in this case. When you initialize your secondary thread, you'd also do uv_async_init
to create a shared async
data structure. This function is also called with a callback that will run whenever your other thread sends a message. That callback is where you would call the JS code to trigger your events.
Here's some semi psuedocode as an example:
In your thread init function called from JS with a single callback arg:
void ThreadInit(const v8::Arguments &args){
// This is just an example, this should be saved somewhere that
// some_callback will be able to access it.
v8::Persistent<v8::Function> js_callback = args[0].As<Function>();
// And save this where you'll be able to call uv_close on it.
uv_async_t async_data;
uv_async_init(uv_default_loop(), &async_data, some_callback);
// initialize the thread and pass it async_data
}
In thread:
async_data.data = (void*) // Some data structure...
uv_async_send(&async_data);
In thread callback:
void some_callback(uv_async_t *async_data){
// Note that this depending on the data, you could easily get thread-safety issues
// here, so keep in mind that you should follow standard processes here.
void* data = async_data->data;
// Process that data however you need to in order to create a JS value, e.g.
// Using NanNew because it is more readable than standard V8.
v8::Local<Number> count = NanNew<Number>(data.count);
v8::Local<v8::Value> argv[] = {
count
};
js_callback->Call(NanNull(), 1, argv);
}
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