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

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

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命令文档 ,这些查询应该按顺序运行。 然而很明显, tableExists (用'yyy'标记)的评估发生在设置值(用'xxx'标记)之前,导致尝试重新创build现有表。
我可以处理这个错误,但我想知道是什么原因造成的,以及将来如何避免这种行为。

一如既往,感谢您的时间。

家伙

文档中的示例2直接解释了您的问题。 在第一次运行时,tableExistsvariables将为false,而SELECT函数仅在事件循环中排队,并且在serialize()中的代码完成之后才会运行。 解决的办法是把if(tableExists)代码放在callback里面SELECT。 这打破了使用序列化的目的,但这是如何工作的。 写入值是好的,因为它们将按照它们被调用的顺序排队,但是需要通过I / O进行响应的东西需要callback,因此需要asynchronous运行。

此外, SQLITE_MISUSE错误来自您在脚本结尾处调用db.close(),但在asynchronouscallback之外的事实。 即使它在脚本的末尾,任何asynchronous的东西都会放到队列中,直到当前函数完成之后才会调用它。

node.js以asynchronous模式工作,但是你的代码是混合同步和asynchronousforms的奇怪forms。

select之后的完整代码应该在callback中,而你的实际代码不会做你想要的,而tableexists将不会有你喜欢的值。

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