使用SQLite3包在Node.js脚本中查询顺序错误

时间:2011-07-29 02:34:41

标签: node.js sqlite package

我正在玩node-sqlite3 package并遇到了一个奇怪的情况。 这个简单的脚本有一个简单的逻辑:查找表是否存在,是否清空,如果没有 - 创建它。

var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('guy.sqlite');    //':memory:'

var tableExists = false;
db.serialize(function() {
    db.get("SELECT name FROM sqlite_master WHERE type='table' AND name='lorem'", function(error, row) {
        tableExists = (row != undefined);
        console.log("xxxxx " +tableExists);
    });

    console.log("yyyyy " +tableExists);

    if (tableExists) {
        console.log("table exists. cleaning existing records");
        db.run("DELETE FROM lorem", function(error) {
            if (error)
                console.log(error);
        });
    }
    else {
        console.log("creating table")
        db.run("CREATE TABLE lorem (info TEXT)", function(error) {
            if (error.message.indexOf("already exists") != -1) {
                console.log(error);
            }
        });
    }
});

db.close();

但我得到的结果是:

yyyyy false
creating table
xxxxx true
{ stack: [Getter/Setter],
  arguments: undefined,
  type: undefined,
  message: 'SQLITE_ERROR: table lorem already exists',
  errno: 1,
  code: 'SQLITE_ERROR' }

根据serialize command documentation,这些查询应该按顺序运行。很明显,tableExists(标有'yyy')的评估发生在设置值(标有'xxx')之前,导致尝试重新创建现有表。
我可以处理错误,但我想知道是什么导致这种情况以及如何在将来避免这种行为。

一如既往,谢谢你的时间。

2 个答案:

答案 0 :(得分:1)

node.js在异步模式下工作,但是你的代码是混合同步和异步形式的一种奇怪的形式。

select之后的完整代码应该在回调中,当你的实际代码没有达到你想要的效果时,tableexists将没有你喜欢的值。

学习爱好node.js的异步模型;)

答案 1 :(得分:1)

文档中的示例2直接解释了您的问题。 tableExists变量在第一次运行时将为false,而SELECT函数仅在事件循环中排队,并且在serialize()中的代码完成之后才会运行。解决方案是将if(tableExists)代码放在回调中以进行SELECT。这违背了使用序列化的目的,但这就是它的工作原理。写入值很好,因为它们将按照调用顺序排队,但需要通过I / O响应的东西需要回调,因此异步运行。

此外,SQLITE_MISUSE错误来自于在脚本末尾调用db.close()但在异步回调之外调用的事实。即使它位于脚本的末尾,任何异步内容都会放入队列中,直到 当前函数完成后才会被调用。