我已经实现了一个需要回调的本机函数。 NodeJS知道接口,但它对它的实现一无所知。此本机函数接收回调,并在结果准备好时调用它。我不希望在没有调用回调的情况下退出事件循环。
这是 这种问题的一个例子。
目前我需要做一些I / O(即使它是一个愚蠢的超时)来强制NodeJS等待我的功能。
在 Boost.Asio我只是实例化一个 work
对象并在调用回调时销毁它。当这个对象被保留时,Boost.Asio的事件循环不会退出。 NodeJS有类似的方法吗?我在NodeJS中使用什么(如果您的答案没有提到计时器,奖金)?
最好的方法是写一个 C ++插件 和使用 一 的 该 手柄 由libuv提供(当然,符合您要求的那个 - 见官方 文件 有关详细信息)。
如果您不想这样做或者您不能这样做(就是这种情况,如果我正确理解了这个问题),那么其他答案中没有提到的可行解决方案就是使用 process.nextTick
安排一个函数,检查每个滴答是否循环可以到期。
看到 这里 有关的更多详细信息 process.nextTick
。
作为一个最小的,工作, 没完没了 例:
var process = require('process')
var stop = false;
var f = function() { if(!stop) process.nextTick(f) }
f()
这样你的功能就是负责设置 stop
控制变量一旦完成执行,循环就会停止。
如果您有多个要等待的回调,只需使用 计数器 并检查它寻找0。
如果您不想在每次添加新函数时显式设置和更新计数器的值(容易出错),您可以轻松编写 发射台 开始增加计数器的功能,并在需要时安排检查下一个计时器。
您还可以将回调作为额外参数传递给函数,以便在它们结束时进行通知,以便它们不必明确处理计数器本身。
使用在下一个计时器上安排的专用功能的一个优点是读者清楚你正在做什么。
另一方面,假的服务器,未来安排的超时或恢复并且从未使用过的I / O流非常模糊,因为读者不知道你为什么这么做。
方法1:创建虚拟服务器(为多个回调更新):
var counter = 0;
var server = require('net').createServer().listen(); // <-- Dummy server
console.log('Dummy server start.');
var ffi = require('ffi'),
ref = require('ref')
var lib = ffi.Library('./libffi_async_demo', {
'print_thread_id': [ 'void', [] ],
'run_delayed': [ 'void', [ 'pointer' ] ],
});
var checkExit = function (){
counter--;
if (counter===0) {
server.close(); // <-- exit Dummy Server
console.log('Dummy server stop.');
}
}
// Wrapper for lib.run_delay()
run_delay = function(cb) {
counter++; // <-- increase counter
lib.run_delayed(cb);
}
var callback1 = ffi.Callback('void', [], function() {
console.log("js callback1 started");
lib.print_thread_id();
console.log("js callback1 finished");
checkExit(); // <-- call at the end of each callback
})
var callback2 = ffi.Callback('void', [], function() {
console.log("js callback2 started");
lib.print_thread_id();
console.log("js callback2 finished");
checkExit(); // <-- call at the end of each callback
})
var callback3 = ffi.Callback('void', [], function() {
console.log("js callback3 started");
lib.print_thread_id();
console.log("js callback3 finished");
checkExit(); // <-- call at the end of each callback
})
run_delay(callback1); // use wrapper
run_delay(callback2); // use wrapper
run_delay(callback3); // use wrapper