提问者:小点点

异步调用某些节点库时Vue电子卡死


我正在尝试使用以下堆栈构建一个应用程序:

  • vue.js
  • 电子

我已经开发了简单的Vue应用程序一段时间了,我了解基本的。 我在这里尝试做的是使用这个令人敬畏的工具:Vue CLI插件电子构建器来结合Vue和Electronic。

虽然我已经成功地用这个堆栈编写了简单的应用程序,但在利用Electronic的nodeIntegration时,我面临着一些问题,因为nodeIntegration应该可以让Node直接访问我的Vue代码。

我对systeminformation库的某些方法的异步调用似乎被卡住了(有时)。 也就是说,当我希望通过调用systeminformation库的异步方法来为视图的数据赋值时,Vue似乎会无限期地挂起并等待。

weired的事情是,有时,当我强制刷新页面时,我可以在控制台中简单地看到当方法返回数据时应该输出的日志。 这几乎就像刷新页面迫使Vue或其他东西更新一样。

我怀疑以下线索,但我可能错了:

  • Vue在我的声明和/或赋值方式中的反应性问题。
  • 节点集成问题,导致VUE+节点没有正确“绑定”。
  • Electronic对一个节点库的打包缺少在Vue中使用的配置,“就像它是一个常规的JS库”。

后一点我不清楚,因为我总是使用Electro+Vue访问节点库,就像使用web库一样。 可能会有更多的原因导致这些问题,但就我所知,这是。。。

您可以创建一个VUE+电子,如下所示:

vue create myapp
vue add electron-builder
yarn add systeminformation

我将为Vue CLI的交互式项目创建保留默认值,因为它们不会对我的问题产生影响。

根据Vue CLI Plugin Electronic Builder关于nodeIntegration的文档,我的Vue.config.js文件如下所示:

module.exports = {
  pluginOptions: {
    electronBuilder: {
      nodeIntegration: true,
    },
  },
};

然后,您可以在方案1和方案2中使用这些片段。

让我们考虑以下示例,其中我使用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数据正确更新,并在Axios调用得到答案后立即显示在我的视图中。

现在,如果我使用相同的逻辑从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>

在这种情况下,我的视图不会显示test数据,因为Vue似乎无限期地挂在systeminformation调用上。 当await语句使挂载的钩子卡住时,控制台日志甚至不会显示。


共1个答案

匿名用户

我刚刚在自己的Electro+Vue应用程序中测试了SystemInformation.getStaticData()函数,结果如下:

它以异步方式执行代码,但是操作非常繁重,这使得应用程序几乎完全没有响应。 它重复产生30个节点的子进程,有效地阻塞3-4个CPU线程。

我认为这可能是getStaticData()函数的错误。 您可能希望在他们的回购中创建一个新问题并报告它。

要么不要使用这个特定的函数,通过运行其他SystemInformation函数来获取所有需要的信息。

启用工作人员中的节点集成:

webPreferences: {
  nodeIntegration: true,
  nodeIntegrationInWorker: true
}

在工作线程中而不是主线程上执行此函数,并将结果发送回您的组件,然后终止工作线程。 但在执行此操作时,请打开“任务管理器”并确保它终止所有派生的子进程:

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()
  }
}
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 })
  }

}

如果worker抛出错误,请尝试将以下内容添加到vue.config/code>:

module.exports = {
  configureWebpack: {
    module: {
      rules: [
        {
          test: /\.worker\.js$/,
          use: { loader: 'worker-loader' }
        }

相关问题