c++ - nodejs 插件异步回调与 libuv

标签 c++ node.js libuv node.js-addon node.js-nan

我有一个调用 native C 库的 Node js 服务。土生土长的图书馆,火灾事件屡屡发生。这些事件被传送到 C 回调函数。我的目标是从此 native C 回调调用 Javascript 回调。

根据我的阅读,我正在使用 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 有一个事件循环,只要有一些挂起的计时器或其他事件等待处理,它就会继续。

参见 this section用于解释事件循环的 node.js 文档。

关于c++ - nodejs 插件异步回调与 libuv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44170900/

相关文章:

c++ - 有符号 C++ 整数的非负范围是否至少与负范围一样大?

c++ - cin 如何将字符转换为相应的类型

c++ - 备份和恢复所有注册表

node.js - V8 引擎在 Node.js 中扮演什么角色?

c - libuv udp echo 服务器关于

c++ - 如何在 nodejs 插件中泵送窗口消息?

c++ - for的递归

sql-server - NodeJS - SQL Server 连接关闭

javascript - 如何避免 Node 中的 UnhandledPromiseRejectionWarning

node.js - NodeJS App.Get 订单错误