2017-05-25 200 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