通过参数防止双重函数调用

时间:2014-02-14 21:58:24

标签: javascript node.js function unique

我的Node.js应用程序中有一个循环,它不断从我的数据库中获取“未处理”的行(每秒1个请求)。

我从数据库收到的每一行都会调用一个具有唯一数字ID的函数,以及来自数据库的其他详细信息作为参数。只要在此函数内处理数据,就会更新数据库,并将该行标记为“已处理”。

function fetch() {
  db.query("SELECT id, data FROM table WHERE processed=0 ORDER BY id ASC", function(err, results) {
    if(results.length > 0) {
        for(var i=0; i<results.length; i++)
            process(results[i].id, results[i].data);
    }
  });
}
var interval_fetch = setInterval(fetch, 1000);

function process(id, data) {
  // Process data
  db.query("UPDATE table SET processed=1 WHERE id="+id);
}

但是,在某些情况下,数据和更新数据库需要一秒钟以上的处理时间。在这种情况下,process()使用相同的参数调用两次甚至更多次。

Node.js环境中最简单的方法是确保只使用某个ID参数同时调用该函数一次?

是否有任何软件包提供此功能并且只需要两到三行额外代码?

(解决方案不一定要防止多次调用该函数。如果我能够检查内部进程(),如果已经使用某个id调用它,我可以在数据之前结束它处理两次。)

3 个答案:

答案 0 :(得分:0)

  

是否有任何软件包提供此功能并且只需要两到三行额外代码?

是:https://github.com/isaacs/once

此外,所有承诺库都应提供开箱即用的功能。和发电机。

但我建议改变你的编码方式,而不是使用它们。 setTimeout而不是setInterval可以通过这种方式消除整个问题:

function fetch() {
  db.query("SELECT id, data FROM table WHERE processed=0 ORDER BY id ASC", function(err, results) {
    if(results.length > 0) {
       for(var i=0; i<results.length; i++)
          process(results[i].id, results[i].data)
    }
    setTimeout(fetch, 1000)
  })
}
var interval_fetch = setTimeout(fetch, 1000)

function process(id, data) {
  // Process data
  db.query("UPDATE table SET processed=1 WHERE id="+id)
}

答案 1 :(得分:0)

简化,在作业完成后设置超时。

function fetch() {
  db.query("SELECT id, data FROM table WHERE processed=0 ORDER BY id ASC", function(err, results) {
    if(results.length > 0) {
        for(var i=0; i<results.length; i++)
            process(results[i].id, results[i].data);
    }
  });
}
setTimeout(fetch, 1000);

function process(id, data) {
  // Process data
  db.query("UPDATE table SET processed=1 WHERE id="+id, function() {
    setTimeout(fetch, 1000);
  });

}

答案 2 :(得分:0)

今天早上我得到了一个相对简单的解决方案。因此,我正在回答我自己的问题。

我只是维护一个对象,其中包含当前已处理但尚未在DB中更新的所有ID。每次调用process()时,我都会检查ID当前是否正在进行,如果适用则取消,然后再处理两次数据。

var in_progress = {}; // Object that contains the IDs

function fetch() {
  db.query("SELECT id, data FROM table WHERE processed=0 ORDER BY id ASC", function(err, results) {
    if(results.length > 0) {
        for(var i=0; i<results.length; i++)
            process(results[i].id, results[i].data);
    }
  });
}
var interval_fetch = setInterval(fetch, 1000);

function process(id, data) {
  if(in_progress.hasOwnProperty(id)) { // Check if ID is in progress
    console.log("ID "+id+" in progress - do nothing");
    return;
  } else {
    in_progress[id] = true; // Insert ID into object

    // Process data here, then run below query

    db.query("UPDATE table SET processed=1 WHERE id="+id, function() {
      // Remove ID from object once DB is updated - Timeout to make sure nothing can overlap with the fetch function
      setTimeout(function(){ delete in_progress[id]; }, 1000); 
    });
  }
}

这完全符合我的要求。我甚至可以制作更快的获取间隔,开始处理来自我的数据库的所有新数据,而没有明显的延迟。仍然没有任何东西会被处理两次。