node.js - node.js 中的异步编程排序问题
问题描述
我选择了一个项目,当第一次启动 node.js 程序时,将不存在数据库。如果数据库表不存在,程序应该创建它们。
但是,在下面的示例程序中,如果数据库在第一次运行时不存在,则不会插入数据,因为 select 语句失败。
下面代码的输出是:
$ node dbtest.js
finished initialise_database
program ended.
select err: { Error: SQLITE_ERROR: no such table: mytable errno: 1, code: 'SQLITE_ERROR' }
successfully created mytable table
database closed.
从日志中可以看出,代码假定同步执行。
我假设正在发生的事情是 node.js 运行时系统使用不同的线程来调度数据库函数以并行运行。
在继续之前,我需要完成 CREATE TABLE 命令。我将如何实现这一目标?
在 node.js 中是否有一些标准的方法来实现这样的事情?
下面的代码:
// npm install sqlite3 - to install sqlite3
const sqlite3 = require('sqlite3').verbose();
let db = initialise_database();
check_and_update(db); //Calling this function upon starting the server.
close_database(db);
console.log('program ended.');
function initialise_database() {
//Establishing a database connection.
let db = new sqlite3.Database('database1.db', (err)=>{
if(err) {
return console.error(err.message);
}
});
// // new db always succeeds even if no file exists - if empty file have to generate table structure
db.run("CREATE TABLE IF NOT exists 'mytable' ('num1' INTEGER, 'num2' INTEGER, 'text1' TEXT);", function(err) {
if (err) {
console.log("Create table error: ", err);
}
console.log("successfully created mytable table");
});
console.log("finished initialise_database");
return db;
}
function check_and_update(db) {
db.all("SELECT * FROM mytable", function(err, data){
if(err) {
console.log("select err: ", err);
} else {
db.run('INSERT INTO mytable (num1, num2, text1) VALUES (?, ?, ?)', [1, 2, 'hi guys!!!'], function(err){
if(err)
console.log("insert err: ", err);
});
}
});
}
function close_database(db) {
db.close((err) => {
if (err) {
return console.error(err.message);
}
console.log('database closed.');
});
}
解决方案
数据库请求是异步的,您必须以异步方式处理它们。
可以是:
Callback
Promise
Async/await
否则,您将尝试对未初始化的数据库执行请求。
这是一个使用Promise
.
const sqlite3 = require('sqlite3').verbose();
let dbPtr = false;
initialise_database()
.then((db) => {
dbPtr = db;
return check_and_update(dbPtr);
})
.then(() => {
close_database(dbPr);
// All is done
console.log('program ended.');
})
.catch((err) => {
// Deal with the error
});
function initialise_database() {
return new Promise((resolve, reject) => {
//Establishing a database connection.
const db = new sqlite3.Database('database1.db', (err) => {
if (err) {
console.error(err.message);
return reject(err);
}
db.run('...', function(err) {
if (err) {
console.log("Create table error: ", err);
return reject(err);
}
console.log("successfully created mytable table");
return resolve(db);
});
});
});
}
function check_and_update(db) {
return new Promise((resolve, reject) => {
db.all('...', function(err, data) {
if (err) {
console.log("select err: ", err);
return reject(err);
}
db.run('...', [1, 2, 'hi guys!!!'], function(err) {
if (err) {
console.log("insert err: ", err);
return reject(err);
}
return resolve();
});
});
});
}
function close_database(db) {
db.close();
}
@编辑
查看文档似乎db.close()
不要在参数中使用回调。我已经修改了片段。
推荐阅读
- lua - ZeroBrane - 使用 NLua 和 Visual Studio 进行调试(适用于 macOS)
- react-native - 在一个场景中渲染所有前端
- c++ - c++ 是否可以“通过引用传递”?
- python-2.7 - 如何使用树莓派和 smtplib 通过电子邮件发送变量值
- c++ - 指向内存分配的指针问题
- google-bigquery - 不包含特定单词的数据的大查询显示结果
- amazon-web-services - 如何从 boto3 的配置文件中检索 mfa_serial?
- vue.js - 通过邮递员成功上传文件但在前端失败(vue)
- wpf - 如何将枚举与 IValueConverter 绑定?
- mysql - 在 jdbc 连接器中使用递增摄取的问题