I'm trying to develop a relative simple test on NodeJS 11.6.x. I'm not really a developer, but sometimes try to do some coding.
My objective is to create a SQLite database and repeat some steps every time a run the code: 1. Drop a table if it exists 2. Create a table 3. Insert N lines 4. Count how many lines is in the database 5. Close the database
I tried first with a basic approach using callback, but couldn't figure out a way to make the step 3 (insert N lines) and looking for a solution, the promise async/await 'pattern' sounded the way to accomplish everything.
But, after refactoring the code, the step 1 (drop table) isn't running and I still not being able to execute step 3 (insert N lines) and have no idea what is happening. I also tried to use a promise package with no luck.
Could someone please have a look and help on this and if possible, explain and or give some advice?
Thanks in advance
Edited: Well, I'not used to post here at SO and don't know the 'right' way to update things here. I beleave I should had left the first code as reference, buy I don't have anymore. Now I think I'm almoust there. All steps are executing in order. Just the step 3 (insert N lines) that I'm not able to make it work. Or it inserts and stops not going to the next '.then' or it just insert 1 line and I'm cannot visualize what is happening. In the code, I commented in two lines with 'BUG 1:' and 'BUG 2:'.
- If I both are commented, I get what is happening, it inserts only 1 line and don't continue the promise chain
- If I comment BUG 1 and let BUG 2 active, it inserts just one line and continues. I think I understand why
- If I comment BUG 2 and let BUG 1 active, it inserts all lines but don't continue and again, I think I understand why
- If I uncomment both (the way I think should work. Don't work, and return an aditional error "Segmentation fault"
Bellow the code:
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')
})
After the great explanation from @CertainPerformance (Thanks a lot), I was able to get it running. I believe it is now "the right" way to do it. May be there are some better ways, but for now, it is ok for me, bellow the final code:
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}`)
})