为什么此示例 Electron 代码不起作用:将降价文件加载到编辑器中?



我的设置

  • 赢10
  • 电子 2.0.1

我遵循的是《电子在行动》一书中的一个例子,第 3 章,其中示例应用程序将 Markdown 文件加载到 Electron 编辑器中,并在双窗格视图中以 HTML 形式显示它。

但是,遵循确切的过程并在本章末尾得出完全相同的源代码。我没有看到作者试图展示的任何内容。

重现:

  1. 运行项目;
  2. 打开一个 .md 文件;
  3. 请注意,这两个窗格为空。

我对此很陌生,无法从控制台中看到任何有用的内容。因此,如果有人可以对以下简短列表进行代码审查,我们将不胜感激!

这是main.js


const { app, BrowserWindow, dialog } = require('electron');
const fs = require('fs');
let mainWindow = null;
app.on('ready', () => {
console.log('Hello from Electron');
mainWindow = new BrowserWindow({
show: false, // Delay showing window to avoid initial blank.
webPreferences: {
nodeIntegration: true
}
});
mainWindow.loadFile('./index.html'); // relpath = same folder as main.js
mainWindow.once('ready-to-show', () => {
mainWindow.show();
})
mainWindow.on('closed', () => {
mainWindow = null;
});
});
const getFileFromUser = exports.getFileFromUser = () => {
const files = dialog.showOpenDialog(mainWindow, {
properties: ['openFile'],
filters: [
{ name: 'Text Files', extensions: ['txt'] },
{ name: 'Markdown Files', extensions: ['md', 'markdown'] }
]
});
if (files) { openFile(files[0]); }
};
const openFile = (file) => {
const content = fs.readFileSync(file).toString();
mainWindow.webContents.send('file-opened', file, content);
}

这是renderer.js

const { remote, ipcRenderer } = require('electron');
const mainProcess = remote.require('./main.js'); // plug in main process
const marked = require('marked'); // import marked as marked
// From document(index.html), find and refer to section '#markdown'
const markdownView = document.querySelector('#markdown');
const htmlView = document.querySelector('#html');
const newFileButton = document.querySelector('#new-file');
const openFileButton = document.querySelector('#open-file');
const saveMarkdownButton = document.querySelector('#save-markdown');
const revertButton = document.querySelector('#revert');
const saveHtmlButton = document.querySelector('#save-html');
const showFileButton = document.querySelector('#show-file');
const openInDefaultButton = document.querySelector('#open-in-default');
const renderMarkdownToHtml = (markdown) => {
htmlView.innerHTML = marked(markdown, { sanitize: true });
};
markdownView.addEventListener('keyup', (event) => {
const currentContent = event.target.value;
renderMarkdownToHtml(currentContent);
});
openFileButton.addEventListener('click', () => {
mainProcess.getFileFromUser();
});
ipcRenderer.on('file-opened', (event, file, content) => {
markdownView.value = content;
renderMarkdownToHtml(content);
});

更新

我在应用程序窗口中打开了开发人员工具,并看到了此错误

remote.js:221 Uncaught Error: Could not call remote method 'getFileFromUser'. Check that the method signature is correct. Underlying error: The "path" argument must be one of type string, Buffer, or URL. Received type undefined
Underlying stack: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be one of type string, Buffer, or URL. Received type undefined
at Object.openSync (fs.js:439:10)
at Object.func (electron/js2c/asar.js:140:31)
at Object.func [as openSync] (electron/js2c/asar.js:140:31)
at Object.readFileSync (fs.js:349:35)
at Object.fs.readFileSync (electron/js2c/asar.js:542:40)
at Object.fs.readFileSync (electron/js2c/asar.js:542:40)
at openFile (pathtohello_electronappmain.js:36:24)
at Object.exports.getFileFromUser (pathtohello_electronappmain.js:32:18)
at electron/js2c/browser_init.js:6620:63
at EventEmitter.<anonymous> (electron/js2c/browser_init.js:6473:21)
at electron/js2c/browser_init.js:6622:17
at EventEmitter.<anonymous> (electron/js2c/browser_init.js:6473:21)
at EventEmitter.emit (events.js:203:13)
at WebContents.<anonymous> (electron/js2c/browser_init.js:3845:23)
at WebContents.emit (events.js:203:13)
pathtohello_electronnode_modulesmarkedlibmarked.js:1541 marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options
checkSanitizeDeprecation @ pathtohello_electronnode_modulesmarkedlibmarked.js:1541

但是查看上面的main.js代码,我找不到路径无效的原因。

更新 2

我发现书籍示例期望返回值showOpenDialog与我的版本不同。

我的 API 文档说showOpenDialog

/**
* Resolve with an object containing the following:
*
* * `canceled` Boolean - whether or not the dialog was canceled.
* * `filePaths` String[] - An array of file paths chosen by the user. If the
* dialog is cancelled this will be an empty array.
* * `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the
* `filePaths` array of base64 encoded strings which contains security scoped
* bookmark data. `securityScopedBookmarks` must be enabled for this to be
* populated.
*
* The `browserWindow` argument allows the dialog to attach itself to a parent
* window, making it modal.
*
* The `filters` specifies an array of file types that can be displayed or selected
* when you want to limit the user to a specific type. For example:
*
* The `extensions` array should contain extensions without wildcards or dots (e.g.
* `'png'` is good but `'.png'` and `'*.png'` are bad). To show all files, use the
* `'*'` wildcard (no other wildcard is supported).
*
* **Note:** On Windows and Linux an open dialog can not be both a file selector
* and a directory selector, so if you set `properties` to `['openFile',
* 'openDirectory']` on these platforms, a directory selector will be shown.
*/

所以我将代码切换为使用files.filePaths,但遇到了新的错误

remote.js:221 Uncaught Error: Could not call remote method 'getFileFromUser'. Check that the method signature is correct. Underlying error: Cannot read property '0' of undefined
Underlying stack: TypeError: Cannot read property '0' of undefined
at Object.exports.getFileFromUser (pathtohelloappmain.js:37:29)
at electron/js2c/browser_init.js:6620:63
at EventEmitter.<anonymous> (electron/js2c/browser_init.js:6473:21)
at EventEmitter.emit (events.js:203:13)
at WebContents.<anonymous> (electron/js2c/browser_init.js:3845:23)
at WebContents.emit (events.js:203:13)
at electron/js2c/browser_init.js:6622:17
at EventEmitter.<anonymous> (electron/js2c/browser_init.js:6473:21)
at EventEmitter.emit (events.js:203:13)
at WebContents.<anonymous> (electron/js2c/browser_init.js:3845:23)
at WebContents.emit (events.js:203:13)

好的,我自己解决了。这本书似乎根据错误/过时的语法使用了showOpenDialogAPI。API 可能曾经是同步的,但后来默认变为异步。我不得不替换示例代码

const getFileFromUser = exports.getFileFromUser = () => {
const files = dialog.showOpenDialog(mainWindow, {
properties: ['openFile'],
filters: [
{ name: 'Text Files', extensions: ['txt'] },
{ name: 'Markdown Files', extensions: ['md', 'markdown'] }
]
});
if (files) { openFile(files[0]); }
};

使用异步版本

const getFileFromUser = exports.getFileFromUser = () => {
dialog.showOpenDialog(mainWindow, {
properties: ['openFile'],
filters: [
{ name: 'Text Files', extensions: ['txt'] },
{ name: 'Markdown Files', extensions: ['md', 'markdown'] }
]
}).then(result => {
if (result.filePaths.length > 0) { openFile(result.filePaths[0]); }
}).catch(err => {
console.log(err);
})
};

此外,返回的承诺包含的内容比书籍示例预期的要多。

修复后,我可以按预期在窗格中看到加载的 Markdown 文件。

最新更新