javascript - 如何强制异步调用函数的顺序执行
问题描述
我对异步代码的想法很陌生,并且仍在努力思考一切是如何工作的。
我正在构建一个将与数据库交互的 Node Express 应用程序。在开发环境中运行时,我希望它与 Sqlite 数据库交互。(生产数据库不会使用Sqlite,这只适用于创建小型开发环境。)
我的问题是我无法控制对数据库的查询的执行顺序和时间。
我想构建我的 SqliteDatabase.js 文件,使其只能按顺序执行查询,尽管该文件中的函数将被异步运行的程序的其他部分调用。
我怎样才能做到这一点?
作为参考,这是我目前设置 SqliteDatabase.js 文件的方式:
var debug = require('debug')('app:DATABASE');
var sqlite = require('sqlite3').verbose();
open = function() {
var db = new sqlite.Database('./test-database.db', sqlite.OPEN_READWRITE | sqlite.OPEN_CREATE, function(err) {
if (err) {
debug("We've encountered an error opening the sqlite database.");
debug(err);
} else {
debug("Sqlite database opened successfully.");
}
});
return db;
}
executeSQLUpdate = function(sql, next) {
var db = open();
db.serialize(function() {
console.log("executing " + sql);
db.run(sql);
db.close();
next();
});
}
exports.executeSQLUpdate = executeSQLUpdate;
有没有办法建立一个队列,当调用“executeSQLUpdate”函数时,请求被添加到队列中,直到所有先前的请求都完成后才开始?
举个例子,看看这段代码,它利用了我的 SqliteDatabase.js 文件:
ar database = require('../../bin/data_access/SqliteDatabase.js');
var createTestTableStmt = "CREATE TABLE IF NOT EXISTS Test(\n" +
"Name TEXT PRIMARY KEY NOT NULL UNIQUE,\n" +
"Age INT NOT NULL,\n" +
"Gender TEXT NOT NULL\n" +
");";
var clearTestTableStmt = "DELETE FROM Test;";
var testInsertStmt = "INSERT INTO Test (Name, Age, Gender)\n" +
"VALUES (\"Connor\", 23, \"Male\");";
createTable = function() {
database.executeSQLUpdate(createTestTableStmt, clearTable);
}
clearTable = function() {
database.executeSQLUpdate(clearTestTableStmt, insertRow);
}
insertRow = function() {
database.executeSQLUpdate(testInsertStmt, function() {
console.log("Done!");
});
}
createTable();
上述代码 10 次中有 9 次运行良好,但每隔一段时间,在调用“clearTable”函数之前调用“insert row”函数,由于违反数据库约束而引发错误。
如何更改 SqliteDatabase.js 文件的实现以避免此问题?
解决方案
You can use async to do this using await
. This code will wait for each asynchronous database call to complete before executing the next line.
async function createTable() {
await database.executeSQLUpdate(createTestTableStmt);
await database.executeSQLUpdate(clearTestTableStmt);
await database.executeSQLUpdate(testInsertStmt);
console.log("Done!");
}
Your console.log
statement will only execute once all three have completed.
I should also mention that you need a try...catch
block around the three database calls to trap any errors and provide an alternate exit point if something should go wrong.
推荐阅读
- javascript - 在 JavaScript 中用新替换旧
- javascript - Ext Js 中的另存为对话框
- python - 所有测试的python补丁
- vba - 在工作表 VBA 中编辑插入行功能
- xslt - xslt/saxon - 将 key() 与 collection() 一起使用:prolog 中不允许内容?
- android-tv - Searchable Android AppTv 上的 SQL 注入漏洞
- enterprise-architect - sparx Enterprise Architect BPMN 步入和退出子模型(复合模型)
- python - CNN 与 Keras 的简单二进制分类,但只得到 50% 的准确率
- php - Laravel 5.6 提交后填充字段
- python - 导致 VerifiedHTTPSConnection 对象的 GET 请求没有属性“_tunnel_host”