2017-05-25 68 views
2

我有一个节点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被多次调用!任何为什么在程序退出后调用它!

任何帮助表示赞赏。

+0

这显然是C++,而不是C,特别是因为(AFAIK)Node.js插件只能用C++而不是C编写。它们是完全不同的语言,如果你想最大限度地获得帮助的可能性,你应该不要调用C++代码“C”。 – Frxstrem

回答

2

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

+0

非常感谢。这解决了我的问题。 –

+0

@ S.Vaghar欢迎来到Stack Overflow。如果答案解决了您的问题,请考虑将其标记为已接受(通过单击左侧的标记)和/或将其提升。这有助于他人在这里找到有用的答案。 – harmic