【问题标题】:Notifying caller about error from callback in node.js on error from sqlite3 call通知调用者有关来自 node.js 中的回调的错误,来自 sqlite3 调用的错误
【发布时间】:2014-04-22 11:54:09
【问题描述】:

在 node.js + sqlite3 中:

什么是从回调通知调用者错误并让调用者重试的好方法?当我们遇到数据库锁定错误时 - 想再次尝试运行查询。

TestController.prototype.addDevices = function (number_of_devices, callback_after_all_devices_have_been_added) {
    var controller = this;
    var db = controller.connectToDb();

    for(i = 0; i < number_of_devices; i++) {
        db.each("SELECT api_key as ak FROM user_table ORDER BY RANDOM() LIMIT 1", function(err, row) {
            //sometimes we get a SQLITE: database locked error
            if (err !== null) {
                console.log("Error found");
                //i-- this will not work - but how do we do it then?
                return;
            }
            console.log("Error: " + err);
            //code to process if we get an entry from the user_table ..
        });
    }
}

【问题讨论】:

  • 由于 for 循环,您会遇到数据库锁定错误。 for 循环不会等待 db.each 完成。在调用 db.each 之后,它会继续进行下一次迭代。
  • 但我想为指定数量的设备(即 for 循环中的计数器)执行 db.each - 我有时会锁定数据库,而且只有十分之一(通常在第一次尝试)
  • 您可以查看 async.eachSeries(异步模块)以确保 db.each 在继续下一个之前完成。由于您的问题是关于如何重试,您可以查看 node-retry 模块,它允许您在失败前重试 x 次。
  • 谢谢!将查看您提到的模块 - 如果我可以使用这些模块解决问题,将发布。是否有任何通用方法可以通过回调通知调用者错误?
  • 我们遵循的约定是在调用回调方法时传递两个参数。 callback(err, result); 万一没有报错,就传error = null。 callback(err); 如果存在错误,则直接传递错误。 callback(null, result);

标签: node.js sqlite callback


【解决方案1】:

这就是我设法解决这个问题的方法 - 添加了一个重试计数器并将问题代码移动到它自己的函数中,并将结尾作为回调传递。它有效 - 但这是一个好方法吗? (除了使用 Promise 或 async 模块?)

TestController.prototype.addDevices = function (number_of_devices, callback_after_all_devices_have_been_added) {
    var number_of_users = 0;
    var controller = this;
    controller.pending_db_writes_for_device = number_of_devices;

    for(i = 0; i < number_of_devices; i++) {
        var api_key = controller.getRandomAPIKeyFromDB(10,function(access_key) {
            var mac_address = controller.generateRandomMAC();
            var friendly_name = Faker.random.array_element(["Washing Machine","Television","Dishwasher","Set top box"]);
            var description = Faker.Lorem.sentence(5);
            controller.registerDeviceWithAPI(mac_address, friendly_name, description, access_key, callback_after_all_devices_have_been_added);
        });
    }
}

TestController.prototype.getRandomAPIKeyFromDB = function (retry_counter, callback) {
  var controller = this;
  var db = controller.connectToDb();
  console.log("Retry counter: "+ retry_counter);
  db.each("SELECT api_key as ak FROM user_table ORDER BY RANDOM() LIMIT 1", function(err, row) {
            if (err !== null) {
                console.log("Error: " + err + "retry count: "+ retry_counter);
                console.log("Error found");
                if(retry_counter === 0) {
                    console.log("Bailing out after retry limit reached");
                    return;
                }
                controller.getRandomAPIKeyFromDB(--retry_counter,callback);
            }
            else {
                console.log("Successfully got api key: " + row.ak);
                callback(row.ak);
            }
        }
    );
}

【讨论】:

  • 你的回调(callback_after_all_devices_have_been_added)会被调用十次吗?这可能是意外行为。
  • 是的...谢谢...我正在检查计数器的 this.pending_db_writes_for_device 并仅当 this.pending_db_writes_for_device 为零时才在 controller.registerDeviceWithAPI 中调用 callback_after_all_devices_have_been_added。但是我现在得到了不同的意外行为。如果您可以查看 - pastie.org/private/ymbkozonqe0ri1k3t78fq 并告诉我可以修复的问题,我将不胜感激。我遇到了意外的行为:有时在 auth 表中创建了重复的条目。错误检查 sqlite3 错误很困难,或者我做错了什么。
猜你喜欢
  • 1970-01-01
  • 2020-08-24
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多