[英]How do I wait to update an HTML header until promise is resolved?
我正在構建我的第一個電子應用程序,我遇到了一個 JS 錯誤,我不知道如何修復。 我已經設法為一個基本的密碼管理器應用程序設置了 IPC。 用例很簡單:
以下是輸入字符串 dog 的預期行為示例:
關鍵字 --> 狗
生成的密碼 --> dog-jdls4ksls
我看到的問題是,我看到的不是打印生成的密碼,而是:
[object Object]-jdls4ksls
我最好的猜測是,因為我使用的是 async/await,所以我打印的是 promise 內存對象而不是返回值。 但是,我不知道如何阻止以等待完成。 提供此輸出的相關代碼是從 HTML 正文調用的 render.js 的最后一行。
任何幫助,將不勝感激!
就上下文而言,我主要是一名后端開發人員,擁有豐富的 python 和 C/C++/C# 經驗。 我的目標是將 C#/.NET GUI 應用程序重新構建為電子應用程序。
這是我所有的代碼。
main.js
const {app, BrowserWindow, ipcMain} = require("electron")
const path = require("path")
function generatePassword(keyword) {
console.log(keyword)
return keyword + '-' + Math.random().toString(36).substring(2,12)
}
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
resizable: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('html/passwordGen.html')
}
app.whenReady().then(() => {
ipcMain.handle("generatePassword", generatePassword)
// console.log(generatePassword('test string')) // works
createWindow()
}).catch(error => {
console.log(error) // log error to console
app.quit() // quit the app
})
preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('main', {
genPW: (keyword) => ipcRenderer.invoke("geåneratePassword", keyword)
})
渲染.js
async function testClick () {
const pw_root = document.getElementById("keyword")
const pw_label = document.querySelector("#password")
pw_label.innerText = await window.main.genPW(pw_root.value)
}
密碼生成.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Password Generator</title>
<link rel="stylesheet" href="../css/style.css">
<script src="../render.js"></script>
</head>
<body>
<h1>Password Generator</h1>
<input type="text" id="keyword" placeholder="Please enter a keyword...">
<button id="btn" onclick="testClick()">Generate Password</button>
<h1 id="password"></h1>
</body>
</html>
編輯:
這是有效的代碼。 接受的解決方案有一個例外,我需要 1)在 generatePassword() 上保持 async/await 或 2)按照另一個解決方案中的建議將其轉換為 .then() 格式。
main.js
const {app, BrowserWindow, ipcMain} = require("electron")
const path = require("path")
function generatePassword(keyword) {
console.log(keyword)
return keyword + '-' + Math.random().toString(36).substring(2,12)
}
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
resizable: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('html/passwordGen.html')
}
app.whenReady().then(() => {
// ipcMain.handle("generatePassword", generatePassword)
// console.log(generatePassword('stink')) // works
ipcMain.handle('generatePassword', (_event, keyword) => {
console.log(keyword); // Testing
return generatePassword(keyword);
});
createWindow()
}).catch(error => {
console.log(error) // log error to console
app.quit() // quit the app
})
preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('main', {
genPW: (keyword) => {
return ipcRenderer.invoke("generatePassword", keyword)
}
})
渲染.js
async function testClick () {
const pw_root = document.getElementById("keyword")
const pw_label = document.querySelector("#password")
pw_label.innerText = await window.main.genPW(pw_root.value)
// window.main.genPW(pw_root.value).then(res => {pw_label.innerText = res})
// ^^^ works as well if async/await removed
}
我不認為你可以使用異步函數作為事件監聽器,你需要在這里使用常規(不是異步)函數。
function testClick() {
const pw_root = document.getElementById("keyword")
const pw_label = document.querySelector("#password")
window.main.genPW(pw_root.value).then(res => {pw_label.innerText = res})
}
另外,您在這里有錯字: invoke("geåneratePassword")
你真的很親近。 使用 Elctron 的invoke
方法是正確的方法。
在您的main.js
文件中,Electron 的 IPC handle
簽名包含channel
和listener
器參數。 在您的代碼中,您調用generatePassword()
函數代替listener
參數。 相反,它應該是(event, ...args)
。 在您的特定情況下(event, keyword)
。 有關更多信息,請參閱ipcMain.handle(channel, listener) 。
此外,在您的preload.js
腳本中,您需要做的就是在您的ipcRenderer.invoke
方法前面添加一個return
語句。
最后,不需要在testClick()
函數上使用async
。 Electron 的invoke
處理所有這些。
main.js
(主進程)
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;
const nodePath = require('path');
// Prevent garbage collection
let window;
function createWindow() {
window = new electronBrowserWindow({
x: 0,
y: 0,
width: 800,
height: 600,
resizable: false,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: nodePath.join(__dirname, 'preload.js')
}
});
window.loadFile('index.html')
.then(() => { window.show(); });
return window;
}
electronApp.on('ready', () => {
window = createWindow();
});
electronApp.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// ---
function generatePassword(keyword) {
console.log(keyword)
return keyword + '-' + Math.random().toString(36).substring(2,12)
}
electronIpcMain.handle('generatePassword', (event, keyword) => {
console.log(keyword); // Testing
return generatePassword(keyword);
});
preload.js
(主進程)
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
contextBridge.exposeInMainWorld(
'main', {
genPW: (keyword) => {
return ipcRenderer.invoke('generatePassword', keyword);
}
});
為簡單起見,我已將您的render.js
腳本包含在結束</body>
標記下方的<script>
標記中。
index.html
(渲染過程)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Emergency</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"/>
</head>
<body>
<div>
<label for="password">Password:</label>
<input type="text" id="password">
<input type="button" id="submit" value="Submit">
</div>
<div>
<label for="generated-password">Generated Password:</label>
<input type="text" id="generated-password" disabled>
</div>
</body>
<script>
document.getElementById('submit').addEventListener('click', () => {
window.main.genPW(document.getElementById('password').value)
.then((generatedPassword) => {
document.getElementById('generated-password').value = generatedPassword;
})
})
</script>
</html>
嘗試在等待中使用雙重等待await (await callToBackend)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.