nodejs addon与libuv的异步回调
我有一个节点js服务调用本地C库。本地图书馆,反复不断地发生火灾事件。这些事件被传递给C回调函数。我的目标是从这个本地C回调调用Javascript回调。nodejs addon与libuv的异步回调
根据我的阅读,我使用uv_async_init和uv_async_send来实现此目标。
我遇到的问题是我的本地C回调函数被调用很多次,并且在那里uv_async_send被多次调用,但传递给uv_async_init的函数仅被调用一次,并且仅在我的程序退出时调用。
这里是我的C代码:
==================================== =================
#include "jsaudio.h"
#include <iostream>
using namespace v8;
static void recordAudioCallback(int index);
void asyncmsg(uv_async_t* handle);
Callback* cbPeriodic;
uv_async_t async;
uv_loop_t* loop;
NAN_METHOD(createEngine) {
std::cout << "==> createEngine\n" ;
}
void createAudioRecorder(const Nan::FunctionCallbackInfo<v8::Value>& info) {
std::cout << "==> createAudioRecorder\n";
}
void startRecording(const Nan::FunctionCallbackInfo<v8::Value>& info) {
std::cout << "==> startRecording\n";
cbPeriodic = new Callback(info[0].As<Function>());
loop = uv_default_loop();
uv_async_init(loop, &async, asyncmsg);
}
void asyncmsg(uv_async_t* handle) {
std::cout << "==> asyncmsg \n";
Nan::HandleScope scope;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
Local<Value> argv[] = { v8::String::NewFromUtf8(isolate, "Hello world") };
cbPeriodic->Call(1, argv);
}
/* This my callback that gets called many times, by a native library*/
static void recordAudioCallback(int index) {
std::cout << "==> recordAudioCallback " << index << "\n";
uv_async_send(&async);
}
========================== ============================
这是我测试的Node.js代码,它上面的原生代码
const jsAudio = new JsAudio({sampleRate: 48000, bufferSize: 8192})
function Test() {
jsAudio.createEngine();
jsAudio.createAudioRecorder();
jsAudio.startRecording(function(error, result) {
if (error) {
console.log('startRecording failed: ' + error);
} else {
console.log('startRecording result: ' + result);
}
});
}
Test();
var waitTill = new Date(new Date().getTime() + 3 * 1000);
while(waitTill > new Date()){}
jsAudio.shutdown();
console.log('program exit...');
============ ==============================================
这里是出:
==> createEngine
==> createAudioRecorder
==> startRecording
==> recordAudioCallback 0
==> recordAudioCallback 1
==> recordAudioCallback 0
==> recordAudioCallback 1
==> recordAudioCallback 0
==> shutdown
program exit...
==> asyncmsg
startRecording failed: Hello world
====================================== =====================
为什么只调用一次asyncmsg!即使recordAudioCallback被多次调用!任何为什么在程序退出后调用它!
任何帮助表示赞赏。
node.js中Javascript代码的实际执行是单线程的。这意味着回调不能在一些已经执行的JS代码中执行。
您的示例代码包含一个连续运行一段时间的繁忙循环,然后程序结束。在执行循环时,没有机会执行回调。
尝试用setTimeout
的呼叫替换该值,以按所需间隔设置超时。像这样的:
const jsAudio = new JsAudio({sampleRate: 48000, bufferSize: 8192})
function Test() {
jsAudio.createEngine();
jsAudio.createAudioRecorder();
jsAudio.startRecording(function(error, result) {
if (error) {
console.log('startRecording failed: ' + error);
} else {
console.log('startRecording result: ' + result);
}
});
}
Test();
setTimeout(function() {
jsAudio.shutdown();
console.log('program exit...');
}, 3000);
请注意,即使setTimeout的调用将立即返回,您的程序不会退出。那是因为node.js有一个事件循环,只要还有一些待处理的定时器或其他等待处理的事件就会继续。
有关事件循环的解释,请参阅node.js文档的this section。
非常感谢。这解决了我的问题。 –
@ S.Vaghar欢迎来到Stack Overflow。如果答案解决了您的问题,请考虑将其标记为已接受(通过单击左侧的标记)和/或将其提升。这有助于他人在这里找到有用的答案。 – harmic
这显然是C++,而不是C,特别是因为(AFAIK)Node.js插件只能用C++而不是C编写。它们是完全不同的语言,如果你想最大限度地获得帮助的可能性,你应该不要调用C++代码“C”。 – Frxstrem