假设您需要执行一些依赖于某个临时文件的操作。由于我们在这里讨论的是Node,这些操作显然是异步的。为了知道何时可以删除临时文件,等待所有操作完成的惯用方法是什么?
下面是一些代码,展示了我想做的事情:
do_something(tmp_file_name, function(err) {});
do_something_other(tmp_file_name, function(err) {});
fs.unlink(tmp_file_name);
但如果我这样写,第三个调用就可以在前两个调用有机会使用该文件之前执行。我需要一些方法来保证前两个调用已经完成(调用了它们的回调),然后在不嵌套调用的情况下继续执行(并在实践中使它们同步)。
我考虑在回调中使用事件发射器,并注册一个计数器作为接收器。计数器将接收已完成的事件,并对仍处于待决状态的操作进行计数。当最后一个完成时,它将删除该文件。但是存在竞争条件的风险,我不确定这通常是如何完成的。
Node人是如何解决这类问题的?
发布于 2011-03-03 04:39:11
最简单的方法是在启动异步操作时递增整数计数器,然后在回调中递减计数器。根据复杂度的不同,回调可以检查计数器是否为零,然后删除该文件。
稍微复杂一点的是维护一个对象列表,每个对象都有标识操作所需的任何属性(甚至可能是函数调用)以及状态代码。回调会将状态代码设置为已完成。
然后,您将有一个等待(使用process.nextTick
)并检查是否所有任务都已完成的循环。与计数器相比,这种方法的优点是,如果所有未完成的任务都可以在所有任务发出之前完成,则计数器技术将导致您过早地删除文件。
发布于 2012-06-11 16:59:29
// simple countdown latch
function CDL(countdown, completion) {
this.signal = function() {
if(--countdown < 1) completion();
};
}
// usage
var latch = new CDL(10, function() {
console.log("latch.signal() was called 10 times.");
});
发布于 2011-03-03 09:38:07
没有“原生”解决方案,但有一个节点的million flow control libraries。您可能会喜欢Step:
Step(
function(){
do_something(tmp_file_name, this.parallel());
do_something_else(tmp_file_name, this.parallel());
},
function(err) {
if (err) throw err;
fs.unlink(tmp_file_name);
}
)
或者,正如Michael建议的那样,计数器可以是一个更简单的解决方案。看看这个semaphore mock-up。你可以这样使用它:
do_something1(file, queue('myqueue'));
do_something2(file, queue('myqueue'));
queue.done('myqueue', function(){
fs.unlink(file);
});
https://stackoverflow.com/questions/5172244
复制相似问题