Cannot read property 'join' of undefined in Javascript file Electron JS

瘦欲@ 提交于 2020-01-06 05:43:30

问题


I have an application in Electron JS that is calling a python function to execute a python script. When the script executes it should send the data back to the Electron JS GUI and display it.

The issue I am having is that it is saying that join is undefined:

weather.js:9 Uncaught TypeError: Cannot read property 'join' of undefined at get_weather (weather.js:9) at HTMLButtonElement.onclick (weather.html:14)

here is my JavaScript file:

let {PythonShell} = require('python-shell')
var path = require("path")

function get_weather() {

  var city = document.getElementById("city").value

  var options = {
    scriptPath : path.join(__dirname, '/../engine/'),
    args : [city]
  }

  let pyshell = new PythonShell('weatherApp.py', options);


  pyshell.on('message', function(message) {
    swal(message);
  })
  document.getElementById("city").value = "";
}

The line "scriptPath : path.join(__dirname, '/../engine/')," seems to be the offending piece of code.

My gui.html file is as follows:

<html>
  <head>
    <title></title>
    <meta charset="UTF-8">
  </head>
  <body>

    <h1>Get your local weather ...</h1>
    <br>
    <br>
    <label>Enter city name here: <label>
    <input id="city" type = "text" placeholder="City">
    <button type = "button" value="clickme" onclick="get_weather()">Get Weather</button>
    <!--- <button class="btn btn-success" onclick="get_weather();">Go!</button> -->
    <br>
    <br>
    <br>
    <script src="/home/ironmantis7x/Documents/BSSLLC/projects/node_electron/electronDemoApps/guiApp/gui/linkers/weather.js"></script>
    <p><button type="button"><a href="gui.html">Back to Main Page</a></button>

  </body>
</html>

What error(s) do I need to fix to get this working correctly?

Thank you.


回答1:


The Problem

Since Electron 5 nodeIntegration is disabled by default in the window. Since normal browser API does not know require or join, you get errors when you try.

Reenabling nodeIntegration

You could enable nodeIntegration again, but it was disabled for a reason. Be sure you read and understand the electron security tutorial.

Using a preload script

Another way is to use a preload script. Let's have a look at the BrowserWindow documentation.

When creating a new BrowserWindow you can add several options. For this case we need the webPreferences.preload option:

Specifies a script that will be loaded before other scripts run in the page. This script will always have access to node APIs no matter whether node integration is turned on or off. The value should be the absolute file path to the script. When node integration is turned off, the preload script can reintroduce Node global symbols back to the global scope.

Be aware that the preload script is run in the renderer process.

Example

Following is an example app, that opens a window with a button that uses the electron dialog to select files. This would not work with disabled nodeIntegration but thanks to our preload script, we reintroduced dialog.showOpenDialog() to our window.

main.js

const { app, BrowserWindow } = require("electron");
const { join } = require("path");

let win;

app.on("ready", () => {
  win = new BrowserWindow({
    webPreferences: {
      //this is the default since electron 5
      nodeIntegration: false,
      //here you load your preload script
      preload: join(__dirname, "preload.js")
    }
  });

  win.loadURL(join(__dirname, "index.html"));
});

preload.js

const { dialog } = require("electron").remote;

window.mystuff = {
  selectFile
};

async function selectFile() {
  const files = await dialog.showOpenDialog({
    properties: ["openFile", "multiSelections"]
  });

  return files;
}

index.html

<html>
  <body>
    <main>
      <button onclick="myFunction()">select file</button>
      <ul id="foo"></ul>
    </main>
    <script>
      async function myFunction() {
        //the function provided by the preload script
        const files = await window.mystuff.selectFile();

        const list = document.getElementById("foo");

        for (const file of files) {
          const node = document.createElement("LI");
          const textNode = document.createTextNode(file);
          node.appendChild(textNode);
          list.appendChild(node);
        }
      }
    </script>
  </body>
</html>

Sending events via IPC

If you are unsure your functionality should be exposed in the window, you can also send events via ipcRenderer.

preload.js

const { ipcRenderer } = require("electron");


window.mystuff = {
  selectFile
};


function selectFile() {
  return new Promise(resolve => {
    ipcRenderer.on("selected-files", (e, files) => {
      resolve(files);
    });

    ipcRenderer.send("select-files");
  });
}

Additional part in main.js


ipcMain.on("select-files", async () => {
  const files = await dialog.showOpenDialog({
    properties: ["openFile", "multiSelections"]
  });

  win.webContents.send("selected-files", files);
});



来源:https://stackoverflow.com/questions/57546385/cannot-read-property-join-of-undefined-in-javascript-file-electron-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!