语境
我正在尝试使用以下堆栈构建应用程序:
我已经开发了一段时间的简单 Vue 应用程序,并且我了解了基础知识。
我在这里尝试做的是使用这个很棒的工具将 Vue 和 Electron 结合起来:Vue CLI Plugin Electron Builder .
虽然我已经成功地使用这个堆栈编写了简单的应用程序,但在利用 Electron 的 nodeIntegration 时遇到了问题。这应该让 Node 直接访问我的 Vue 代码。
问题
我对 systeminformation 的一些方法的异步调用图书馆似乎被卡住了(有时)。
也就是说,当我想通过调用 systeminformation 的异步方法来为我的 View 数据赋值时库,Vue 似乎无限期地挂起和等待。
奇怪的是,有时,当我强制刷新页面时,我可以在控制台中简要地看到该方法返回数据时应该输出的日志。
这几乎就像刷新页面强制 Vue 或其他东西更新一样。
我怀疑以下线索,但我可能错了:
后一点我不清楚,因为我一直使用 Electron+Vue 访问 Node 库,就像访问 Web 库一样。
可能还有更多可能导致这些问题,但据我所知……
重现步骤
您可以按如下方式创建 Vue+Electron:
vue create myapp
vue add electron-builder
yarn add systeminformation
I'm leaving default values for Vue CLI's interactive project creation as they don't have an impact on my issue.
根据 Vue CLI Plugin Electron Builder 关于 nodeIntegration 的文档, 我的
vue.config.js
文件如下所示:module.exports = {
pluginOptions: {
electronBuilder: {
nodeIntegration: true,
},
},
};
然后您可以使用 中的片段场景一 和 场景二 .方案 1
让我们考虑以下示例,其中我使用 Axios 分配值:
<template>
<pre>{{ test }}</pre>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
test: null,
};
},
async mounted() {
console.log("Getting data from Axios...");
// Assign a value to the "test" data with an asynchronous HTTP call with Axios.
this.test = (
await axios.get("https://cat-fact.herokuapp.com/facts")
).data;
// It gets there as soon as the server responds.
console.log("Got it!", this.test);
},
};
</script>
在这里,异步调用按预期工作,我的 test
数据正确更新并在我的 View 中显示 Axios电话得到了答复。方案 2
现在,如果我使用相同的逻辑从 systeminformation 的方法中获取数据图书馆:
<template>
<pre>{{ test }}</pre>
</template>
<script>
import systeminformation from "systeminformation";
export default {
data() {
return {
test: null,
};
},
async mounted() {
console.log("Getting data from systeminformation...");
// Assign a value to the "test" data with an asynchronous call to a method of systeminformation.
this.test = await systeminformation.getStaticData();
// It just won't get there most of the time...
console.log("Got it!", this.test);
},
};
</script>
在这种情况下,我的 View 不会显示 test
Vue 的数据似乎卡在 systeminformation无限期地打电话。控制台日志甚至不会显示,因为 await 语句似乎使
mounted
钩子(Hook)卡住了。
最佳答案
我刚刚测试了systeminformation.getStaticData()
在我自己的 Electron + Vue 应用程序中运行,结果如下:
它异步执行代码,但操作非常繁重,使应用程序几乎完全没有响应。它反复产生约 30 个 Node 子进程,有效地阻塞了 3-4 个 CPU 线程。
我认为这可能是 getStaticData()
的错误功能。您可能想在他们的仓库中创建一个新问题并报告它。
解决方案
要么不要使用这个特定的功能,而是通过运行其他 systeminformation
来获取所有需要的信息。职能。
或者
在工作人员中启用 Node 集成:
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true
}
在工作线程中执行此函数,而不是在主线程上,并将结果发送回您的组件,然后终止工作线程。虽然当你这样做时,打开任务管理器并确保它终止所有产生的子进程:Vue 组件
import sysInfoWorker from 'worker-loader!./workers/sysInfoWorker'
data () {
return {
sysInfoWorker: null
}
},
mounted () {
this.initSysInfoWorker()
},
methods: {
initSysInfoWorker () {
this.sysInfoWorker = new sysInfoWorker()
try {
this.sysInfoWorker.onmessage = (event) => {
console.log('sysInfoWorker message:', event)
this.test = event
}
this.sysInfoWorker.onerror = (error) => {
console.log('sysInfoWorker error:', error)
}
}
catch (error) {
console.log(error)
}
},
startSysInfoWorker () {
this.sysInfoWorker.postMessage({
operation: 'run:getStaticData'
})
},
cancelSysInfoWorker () {
this.sysInfoWorker.postMessage('cancel:getStaticData')
// this.sysInfoWorker.terminate()
}
}
worker const systeminformation = require('systeminformation')
const state = { cancelled: false }
// Listen to messages from parent thread
self.addEventListener('message', (event) => {
if (event.data === 'cancel:getStaticData') {
state.cancelled = true
}
else {
state.cancelled = false
initWorker(event)
}
})
async function initWorker (event) {
if (event.data.operation === 'run:getStaticData') {
const info = await systeminformation.getStaticData()
self.postMessage({ info: info })
}
}
如果工作人员抛出错误,请尝试将以下内容添加到您的 vue.config
:module.exports = {
configureWebpack: {
module: {
rules: [
{
test: /\.worker\.js$/,
use: { loader: 'worker-loader' }
}
关于node.js - Vue Electron 在异步调用一些 Node 库时卡住了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63088031/