【发布时间】:2019-07-06 18:59:27
【问题描述】:
我正在尝试在 NodeJS 11.6.x 上开发一个相对简单的测试。我不是真正的开发人员,但有时会尝试编写一些代码。
我的目标是创建一个 SQLite 数据库并在每次运行代码时重复一些步骤: 1. 删除一个表,如果它存在 2.创建表 3.插入N行 4.统计数据库中有多少行 5. 关闭数据库
我首先尝试了使用回调的基本方法,但无法找到实现步骤 3(插入 N 行)并寻找解决方案的方法,promise async/await 'pattern' 听起来是完成的方法一切。
但是,在重构代码之后,步骤 1(删除表)没有运行,我仍然无法执行步骤 3(插入 N 行)并且不知道发生了什么。我也尝试使用一个没有运气的承诺包。
有人可以对此进行查看并提供帮助,如果可能的话,请解释或提供一些建议?
提前致谢
已编辑:嗯,我不习惯在 SO 上发帖,也不知道在这里更新内容的“正确”方式。我相信我应该留下第一个代码作为参考,买我没有了。 现在我想我快到了。所有步骤都按顺序执行。只是我无法使其工作的第 3 步(插入 N 行)。或者它插入并停止不进入下一个'.then',或者它只是插入 1 行,我无法想象正在发生的事情。 在代码中,我用“BUG 1:”和“BUG 2:”注释了两行。
- 如果我俩都被评论了,我就会知道发生了什么,它只插入 1 行并且不继续承诺链
- 如果我评论 BUG 1 并激活 BUG 2,它只插入一行并继续。我想我明白为什么
- 如果我评论 BUG 2 并激活 BUG 1,它会插入所有行但不会再继续,我想我明白为什么
- 如果我取消注释两者(我认为应该工作的方式。不要工作,并返回附加错误“分段错误”
下面的代码:
const sqlite3 = require('sqlite3')
let db = new sqlite3.Database('./test.db');
waitTime = 1
process.stdout.write('Starting...\n')
var test = new Promise((resolve, reject) => {
process.stdout.write('Drop Table... ');
db.run(`DROP TABLE IF EXISTS test`, (err) => {
if (err) {
process.stdout.write(`Dropping Error ${err.message}\n`)
reject()
} else {
setTimeout(() => {
process.stdout.write(`Dropped!\n`)
resolve()
}, waitTime)
}
})
})
test.then(() => {
return new Promise((resolve, reject) => {
process.stdout.write('Create Table... ')
db.run(`CREATE TABLE IF NOT EXISTS test (data TEXT)`, (err) => {
if (err) {
process.stdout.write(`Creating Error ${err.message}\n`)
reject()
} else {
setTimeout(() => {
process.stdout.write(`Created!\n`)
resolve()
}, waitTime)
}
})
})
}).then(() => {
return new Promise((resolve, reject) => {
process.stdout.write('Insert Line... ')
lines = 10
let loop = (async () => {
for (let i = 0; i < lines; i++) {
await new Promise(resolve =>
db.run(`INSERT INTO test (data) VALUES ('a')`, (err) => {
if (err) {
process.stdout.write(`Inserting Error ${err.message}\n`)
throw (err)
} else {
setTimeout(() => {
// process.stdout.write(`Line ${i} Inserted!\n`)
process.stdout.write(`, ${i+1}`)
resolve() // BUG 1: if this line is commented, comment it, it will insert only 1 line
}, waitTime)
}
})
)
}
})()
process.stdout.write(`, IDone\n`)
resolve() // BUG 2: If this line is commented, the promise chain stops here
})
}).then(() => {
return new Promise((resolve, reject) => {
process.stdout.write('Count Line(s)... ')
db.all(`SELECT COUNT(*) AS totalLines FROM test`, [], (err, rows) => {
if (err) {
process.stdout.write(`Count Error ${err.message}\n`)
reject()
} else {
setTimeout(() => {
process.stdout.write(` ${rows[0].totalLines} Count!\n`)
resolve()
}, waitTime)
}
})
})
}).then(() => {
return new Promise((resolve, reject) => {
process.stdout.write('Select Line(s)... ')
db.all('SELECT data FROM test', [], (err, rows) => {
if (err) {
process.stdout.write(`Select Error ${err.message}\n`)
reject()
} else {
rows.forEach((row) => {
console.log(row.data);
})
setTimeout(() => {
process.stdout.write(`${rows[0].totalLines} Select!\n`)
resolve()
}, waitTime)
}
})
})
}).then(() => {
return new Promise((resolve, reject) => {
process.stdout.write('Close DB... ')
db.close((err) => {
if (err) {
process.stdout.write(`Closing Error ${err.message}\n`)
reject()
} else {
setTimeout(() => {
process.stdout.write(`Closed!\n`)
resolve()
}, waitTime)
}
})
})
}).then(() => {
console.log('Finished')
})
经过@CertainPerformance 的精彩解释(非常感谢),我能够让它运行起来。我相信现在是“正确”的做法。可能有一些更好的方法,但现在对我来说没问题,下面是最终代码:
const sqlite3 = require('sqlite3')
let db = new sqlite3.Database('./test.db');
lines = 10
process.stdout.write('Starting... ')
var test = new Promise((resolve, reject) => { process.stdout.write(`Promise Created...!\n`)
resolve()
})
test.then(() => { process.stdout.write('Drop Table... ')
return new Promise((resolve, reject) => {
db.run(`DROP TABLE IF EXISTS test`, (err) => {
if (err) {
reject(err)
} else { process.stdout.write(`Dropped!\n`)
resolve() }
})
})
}).then(() => { process.stdout.write('Create Table... ')
return new Promise((resolve, reject) => {
db.run(`CREATE TABLE IF NOT EXISTS test (data TEXT)`, (err) => {
if (err) {
reject(err)
} else {
process.stdout.write(`Created!\n`)
resolve() }
})
})
}).then(() => { process.stdout.write('Insert Line... ')
let insertLoop = (async () => {
for (let i = 0; i < lines; i++) {
await new Promise(resolve =>
db.run(`INSERT INTO test (data) VALUES ('a')`, (err) => {
if (err) {
reject(err)
} else { ( i == 0 ) ? process.stdout.write(`${i + 1}`) : process.stdout.write(`, ${i + 1}`)
resolve() }
})
)
}
process.stdout.write(`, Inserted!\n`)
})()
return insertLoop
}).then(() => { process.stdout.write('Count Line(s)... ')
return new Promise((resolve, reject) => {
db.all(`SELECT COUNT(*) AS totalLines FROM test`, [], (err, rows) => {
if (err) {
reject(err)
} else { process.stdout.write(` ${rows[0].totalLines} Counted!\n`)
resolve()
}
})
})
}).then(() => { process.stdout.write('Close DB... ')
return new Promise((resolve, reject) => {
db.close((err) => {
if (err) {
reject(err)
} else { process.stdout.write(`Closed!\n`)
resolve()
}
})
})
}).then(() => {
console.log('Finished')
}).catch((err) => {
process.stdout.write(`The process did not finish successfully: ${err}`)
})
【问题讨论】:
-
只尝试
awaitPromises的表达式 -
我阅读了那篇文章并对代码进行了一些更改,并在此处重新发布,第一步仍然错误,我无法弄清楚为什么。 Promise 不应该在 db.run 回调发送“resolve 信号”之后“resolve”吗?
-
代码现在看起来很好,您确定输出与问题中列出的一样吗?因为
Dropped! (Callback)在resolve()之前运行,所以Finished不应该有任何方法在Dropped!被记录之前记录。 -
感谢您的关注。是的,我又做错了,它正在工作......现在我再次重建并更新了一些改进,但仍然有错误。
标签: node.js promise async-await