电子 contextBridge returns 未定义
Electron contextBridge returns undefined
我有这 4 个项目文件:
main.js
preload.js
renderer.js
index.html
节点:17.4.0
电子:18.2.0
我试图在我的文件系统上打开一个文本文件,由 renderer.js 的点击事件触发 - 然后将文本文件的内容加载到 [= index.html.
中的 15=] 标签
main.js
const {app, BrowserWindow, ipcMain} = require("electron");
const path = require("path");
const fs = require("fs");
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false
}
});
mainWindow.loadFile(path.join(__dirname, "index.html"));
// Open the DevTools.
mainWindow.webContents.openDevTools();
};
app.on("ready", () => {
createWindow();
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
function openFile(){
fs.readFile("logs.txt", "utf8", (err, data) => {
if (err) {
console.error(err);
return "Error Loading Log File";
}
console.log(data);
return data;
});
}
ipcMain.handle("channel-load-file", openFile);
preload.js
const {contextBridge, ipcRenderer} = require("electron");
contextBridge.exposeInMainWorld("electronAPI", {
loadFile: () => ipcRenderer.invoke("channel-load-file")
});
renderer.js
const btn = document.querySelector("#btn");
btn.addEventListener("click", e => {
let data = window.electronAPI.loadFile();
document.getElementById("main-content").innerText = data;
});
我肯定能在main.js
中看到console.log(data);
里面的Log文件的内容
但是,<div id="main-content"></div>
填充了 undefined。
我认为我遗漏了其中的一些关键步骤:preload.js
或 renderer.js
有人看到事件链在哪里丢失了吗?
(我对流程的任何改进都持开放态度)
在下面的代码中插入 console.log()
表示 handle
内容在 openFile
之前执行
有机会 return 结果。
main.js
(主进程)
function openFile() {
fs.readFile("logs.txt", "utf-8", (err, data) => {
if (err) {
console.error(err);
return "Error Loading Log File";
}
console.log('openFile: ' + data); // Testing
return data;
});
}
ipcMain.handle('channel-load-file', () => {
let result = openFile();
console.log('handle: ' + result); // Testing
return result;
})
console.log()
结果是...
handle: undefined
openFile: File content...
要解决此问题,让我们将 fs.readFile
从回调更改为承诺,这样我们就可以在 handle
.
中为它 await
由于 handle
处理的是承诺,让我们使用语法糖 async
和 await
来简化实现。
main.js
(主进程)
function openFile() {
return new Promise((resolve, reject) => {
fs.readFile("logs.txt", "utf-8", (error, data) => {
if (error) {
console.log('reject: ' + error); // Testing
reject(error);
} else {
console.log('resolve: ' + data); // Testing
resolve(data)
}
});
});
}
ipcMain.handle('channel-load-file', async (event, message) => {
return await openFile()
.then((data) => {
console.log('handle: ' + data); // Testing
return data;
})
.catch((error) => {
console.log('handle error: ' + error); // Testing
return 'Error Loading Log File';
})
});
最后,让我们修改在 index.html
文件中检索 data
的方式。
PS:让我们也将 .toString()
添加到 returned data
(只是为了确定)。
index.html
(渲染过程)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Electron Test</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"/>
</head>
<body>
<div id="main-content"></div>
<input type="button" id="button" value="Load File">
</body>
<script>
document.getElementById('button').addEventListener('click', () => {
window.electronAPI.loadFile()
.then((data) => {
console.log(data); // Testing
document.getElementById("main-content").innerText = data.toString();
});
})
</script>
</html>
我有这 4 个项目文件:
main.js
preload.js
renderer.js
index.html
节点:17.4.0 电子:18.2.0
我试图在我的文件系统上打开一个文本文件,由 renderer.js 的点击事件触发 - 然后将文本文件的内容加载到 [= index.html.
中的 15=] 标签main.js
const {app, BrowserWindow, ipcMain} = require("electron");
const path = require("path");
const fs = require("fs");
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false
}
});
mainWindow.loadFile(path.join(__dirname, "index.html"));
// Open the DevTools.
mainWindow.webContents.openDevTools();
};
app.on("ready", () => {
createWindow();
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
function openFile(){
fs.readFile("logs.txt", "utf8", (err, data) => {
if (err) {
console.error(err);
return "Error Loading Log File";
}
console.log(data);
return data;
});
}
ipcMain.handle("channel-load-file", openFile);
preload.js
const {contextBridge, ipcRenderer} = require("electron");
contextBridge.exposeInMainWorld("electronAPI", {
loadFile: () => ipcRenderer.invoke("channel-load-file")
});
renderer.js
const btn = document.querySelector("#btn");
btn.addEventListener("click", e => {
let data = window.electronAPI.loadFile();
document.getElementById("main-content").innerText = data;
});
我肯定能在main.js
中看到console.log(data);
里面的Log文件的内容
但是,<div id="main-content"></div>
填充了 undefined。
我认为我遗漏了其中的一些关键步骤:preload.js
或 renderer.js
有人看到事件链在哪里丢失了吗?
(我对流程的任何改进都持开放态度)
在下面的代码中插入 console.log()
表示 handle
内容在 openFile
之前执行
有机会 return 结果。
main.js
(主进程)
function openFile() {
fs.readFile("logs.txt", "utf-8", (err, data) => {
if (err) {
console.error(err);
return "Error Loading Log File";
}
console.log('openFile: ' + data); // Testing
return data;
});
}
ipcMain.handle('channel-load-file', () => {
let result = openFile();
console.log('handle: ' + result); // Testing
return result;
})
console.log()
结果是...
handle: undefined
openFile: File content...
要解决此问题,让我们将 fs.readFile
从回调更改为承诺,这样我们就可以在 handle
.
await
由于 handle
处理的是承诺,让我们使用语法糖 async
和 await
来简化实现。
main.js
(主进程)
function openFile() {
return new Promise((resolve, reject) => {
fs.readFile("logs.txt", "utf-8", (error, data) => {
if (error) {
console.log('reject: ' + error); // Testing
reject(error);
} else {
console.log('resolve: ' + data); // Testing
resolve(data)
}
});
});
}
ipcMain.handle('channel-load-file', async (event, message) => {
return await openFile()
.then((data) => {
console.log('handle: ' + data); // Testing
return data;
})
.catch((error) => {
console.log('handle error: ' + error); // Testing
return 'Error Loading Log File';
})
});
最后,让我们修改在 index.html
文件中检索 data
的方式。
PS:让我们也将 .toString()
添加到 returned data
(只是为了确定)。
index.html
(渲染过程)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Electron Test</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"/>
</head>
<body>
<div id="main-content"></div>
<input type="button" id="button" value="Load File">
</body>
<script>
document.getElementById('button').addEventListener('click', () => {
window.electronAPI.loadFile()
.then((data) => {
console.log(data); // Testing
document.getElementById("main-content").innerText = data.toString();
});
})
</script>
</html>