#javascript #node.js #electron #electron-forge #node-sqlite3
Вопрос:
Хорошо, у меня есть эти методы в моем index.js основной процесс, к которому я хочу получить доступ из процесса рендеринга. Я попробовал два способа осуществить этот процесс.
ipcMain и ipcRender
Первая идея состояла в том, чтобы использовать ipcMain и ipcRender с помощью «on» и «sendSync». Я получаю сообщение об ошибке «объект не может быть клонирован».
Index.js — Основной процесс
ipcMain.on( "getData", ( event, callBack ) => {
db = new sqlite3.Database(
dbPath,
sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE,
function(error) {
if(error){
log.error(`exception: ${error}`);
//throw error
if (callBack) callBack(error);
}
data.getModel(db, log, function(rawDataStr) {
if (callBack) callBack(rawDataStr);
})
}
)
return db
} );
App.Js — Процесс Рендеринга
window.require('electron').ipcRenderer.sendSync( "getData",function(rawData){
if (rawData.name amp;amp; rawData.name == 'Error') {
alert('PRT DB is not present');
} else {
sharedObj.rawData = rawData;
app.advanceReadiness();
}
})
@электронный/дистанционный
Другим решением, которое я попробовал, было использование @electron/remote. Я понимаю, что удаленный модуль был изношен, но я был готов попробовать его. Это работает, когда я запускаю приложение локально, но как только я создаю приложение с помощью electron-forge, оно больше не может найти мою глобальную переменную.
Index.js — Основной процесс
require('@electron/remote/main').initialize()
global.sharedObj = {
getData:function(callBack){
db = new sqlite3.Database(
dbPath,
sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE,
function(error) {
if(error){
log.error(`exception: ${error}`);
//throw error
if (callBack) callBack(error);
}
data.getModel(db, log, function(rawDataStr) {
if (callBack) callBack(rawDataStr);
})
}
)
}
}
App.js — Процесс Рендеринга
var sharedObj = window.require('@electron/remote').getGlobal('sharedObj');
sharedObj.getData(function (rawData) {
if (rawData.name amp;amp; rawData.name == 'Error') {
alert('PRT DB is not present');
} else {
sharedObj.rawData = rawData;
app.advanceReadiness();
}
});
Комментарии:
1. Я не использовал sqlite с electron,
new sqlite3.Database
создает ли соединение с базой данных или вы выполняете запрос?
Ответ №1:
Я подозреваю, что ваше соединение с БД невозможно клонировать, потому что этот объект БД не соответствует одному из допустимых значений, которые могут быть сериализованы с помощью IPC (межпроцессная связь). (Смотрите этот раздел, чтобы узнать, что мы можем передать между рендерером > основным процессом без проблем).
Вам, вероятно, нужно сделать что-то подобное. Я не знаком с использованием sqlite3 в JS, но, надеюсь, это поможет вам начать на правильном пути. Общая суть заключается в том, что вы должны хранить ссылку на свою базу данных в своем main.js файл, а затем настройте прослушиватель, который будет прослушивать запросы с вашей начальной страницы. Как только сообщение будет отправлено на main.js файл (т. е. серверная часть), вы запросите свою базу данных, а затем вернете результаты на внешний интерфейс, отправив сообщение IPC обратно ( win.webContents.send("fromMain", data);
в примере elow).
main.js
const {
app,
BrowserWindow,
ipcMain
} = require("electron");
const path = require("path");
const fs = require("fs");
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;
let db = new sqlite3.Database(
dbPath,
sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE,
function (error) {
if (error) {
log.error(`exception: ${error}`);
//throw error
if (callBack) callBack(error);
}
data.getModel(db, log, function (rawDataStr) {
if (callBack) callBack(rawDataStr);
})
}
);
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false, // is default value after Electron v5
contextIsolation: true, // protect against prototype pollution
enableRemoteModule: false, // turn off remote
preload: path.join(__dirname, "preload.js") // use a preload script
}
});
// Load app
win.loadFile(path.join(__dirname, "dist/index.html"));
// rest of code..
}
app.on("ready", createWindow);
ipcMain.on("toMain", (event, args) => {
db.retrieveData().then(data => {
// Send result back to renderer process
win.webContents.send("fromMain", data);
});
});
preload.js
const {
contextBridge,
ipcRenderer
} = require("electron");
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
"api", {
send: (channel, data) => {
// whitelist channels
let validChannels = ["toMain"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
let validChannels = ["fromMain"];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
}
}
);
index.html
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8"/>
<title>Title</title>
</head>
<body>
<script>
window.api.receive("fromMain", (data) => {
console.log(`Received ${data} from main process`);
});
window.api.send("toMain", "some data");
</script>
</body>
</html>