Электрон: Выполнить sqlite (лучше-sqlite) операции с БД в другом потоке
Я разрабатываю настольное приложение, используя платформу Electron, и мне нужно использовать базу данных sqlite для данных приложения. Я решил использовать better-sqlite3
потому что:
- Поддержка пользовательских функций SQL (для меня это очень важно)
- Это намного быстрее чем
node-sqlite3
в большинстве случаев - Это просто в использовании.
- Это синхронный API (в большинстве случаев мне нужно сериализовать данные)
но в некоторых случаях, когда я выполняю запрос, для ответа которого требуется некоторое время, пользовательский интерфейс приложения не отвечает пользователю, пока запрос не завершится.
Как я могу выполнить несколько запросов БД в другом потоке? или запустить их асинхронно (как node-sqlite3
)?
Извините за плохой английский
1 ответ
Узел позволяет вам отдельный процесс " из коробки". (Потоки - это другое дело - увы, нет WebWorkers:(хотя вы можете найти дополнение к потоку lib где-нибудь.
У меня была та же проблема, что и у вас - мне нужен синхронный код для запуска без блокировки основного потока, и я использовал дочерний процесс. Это было для лучшего sqlite тоже!
Проблема в том, что обработка io-потоков, sigints и т. Д. Для контроля не сразу очевидна и зависит от того, работаете ли вы на windows или posix.
Я использую разветвленный дочерний процесс с параметром silent, установленным в true, для синхронной работы с БД
Если вам нужен контроль над этим процессом или отчеты об обновлении прогресса обратно в основной процесс для графического интерфейса пользователя во время синхронизации; Я контролирую / связываюсь с дочерним процессом, читая / записывая в stdin/out дочернего процесса с использованием fileSystem writeFileSync / readFileSync в различных точках моего дочернего процесса (вы не можете использовать обычные api межпроцессных comms во время операций синхронизации, так как это управляемый событиями и не может работать во время выполнения синхронного кода. Хотя вы можете смешивать и сочетать два типа io)
пример разветвленного дочернего процесса;
//parent.js and child.js in same folder
//parent.js
process.on('exit', (code) => {
console.log(`Parent to exit with code: ${code}`);
});
const readLine = require("readline") ;
const cp = require('child_process');
var forkOptions = {
//execArgv:['--inspect-brk'], // uncomment if debugging the child process
silent:true // child gets own std pipes (important) whch are piped to parent
};
var childOptions = [] ;
const child = cp.fork(`./child.js`,childOptions,forkOptions);
//for messages sent from child via writeSync
const childChannel = readLine.createInterface({
input: child.stdout
}).on("line",function(input){
console.log("writeSync message received from child: " + input) ;
});
//for messages sent from child via process.send
child.on('message', (m) => {
console.log("process.send message received from child: " + m) ;
});
// Child.js
process.on('exit', (code) => {
console.log(`Child to exit with code: ${code}`);
});
const fs = require('fs');
function doSyncStuff(){
for(let i = 0 ; i < 20 ; i++){
//eg. sync db calls happening here
process.send(`Hello via process.send from child. i = ${i} \n`); // async commms . picked up by parent's "child.on" event
fs.writeFileSync(process.stdout.fd,`Hello via writeFileSync from child. i = ${i} \n`) ; // sync comms. picked up by parent's readLine listener ("process" here is the child )
}
}
doSyncStuff();