Uncaught ReferenceError: Cannot access 'socket' before initialization only on electron - javascript

I am trying to set up an electron app where i send a message to the server, and the server puts the value on the readonly textarea.
But, when i start the app, i see this in the devtoools console:
Uncaught ReferenceError: Cannot access 'socket' before initialization
But, when i open my browser (outside the electron app), it works as i wanted
why my code works as planned on my browser, but not on my electron?
//SERVER HOSTING SECTION
const express = require('express')
const http = require('http')
const socketIo = require('socket.io')
const serverapp = express()
const server = http.createServer(serverapp)
let mensagem
serverapp.use(express.static(__dirname+'/data'))
const io = socketIo.listen(server);
server.listen(8889, ()=>console.log("adm online na porta http://localhost:7000"))
serverapp.get("/",function(req,res){
res.sendFile(path.resolve("index.html"));
})
io.on('connection', (socket) => {
console.log("nova conexao")
socket.on('mensagem',(mensagem)=>{
console.log("mensagem aqui:", mensagem)
io.emit('resposta',mensagem)
})
});
//ELECTRON APP SECTION
const {app, BrowserWindow} = require('electron')
const path = require('path')
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('data/index.html')
//mainWindow.loadURL("http://localhost:7000/index.html");
// Open the DevTools.
mainWindow.webContents.openDevTools()
}
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
/*
$.getScript("server.js",function(){
console.log("a")
})
*/
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="estilo.css">
<script src="socket.io/socket.io.js"></script>
<title>Hello World!</title>
</head>
<body>
<h1>aaaaaaaaaa</h1>
<div>
<input type="text" id="textbox" value="aba">
<button onclick ="adicionar()"type="button" id="botao" for="textbox">Enviar</button>
<button onclick ="enviar()"type="button" id="botao2" >Teste</button>
</div>
<textarea name="" id="textarea" cols="30" rows="10" readonly></textarea>
<script src="codigo.js"></script>
</body>
</html>
<!-- begin snippet: js hide: false console: true babel: false -->
// code that sends and receives the message
let botaoAdicionar=document.querySelector("#botao")
let textbox = document.querySelector('#textbox')
let textarea = document.querySelector("#textarea")
let valortextbox;
console.log(valortextbox)
const socket = io.connect()
function adicionar(){
event.preventDefault();
console.log(textbox.value)
textarea.value+=textbox.value
};
socket.on('resposta',(mensagem)=>{
textarea.textContent+=mensagem
console.log('resposta recebida')
})
function enviar(){
let valortextbox= textbox.value
socket.emit('mensagem', valortextbox)
console.log("a")
}
/*
let testbtn=document.querySelector("#botao2")
testbtn.addEventListener("click", function(){
console.log("a")
})
*/

Problem solved, i just needed to add "nodeIntegration: true" on browser window
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
preload: path.join(__dirname, 'preload.js')
}
})

Related

electron Cannot read properties of undefined

It is my first time using electron and I faced this error while creating a quit button.
I went thru like 50 threads and most of them said use require('#electron/remote/main').initialize()
and it did not work
electron version :20.1.1
should I downgrade electron to work?
or should I reinstall electron?
or maybe create a new project?
Uncaught TypeError: Cannot read properties of undefined (reading 'getCurrentWindow')
at document.getElementById.onclick (render.js:6:25)
my index.js file:
const { app, BrowserWindow } = require('electron');
const path = require('path');
require('#electron/remote/main').initialize();
if (require('electron-squirrel-startup')) {
app.quit();
}
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
frame: false,
enableRemoteModule: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
webPreferences: true,
preload: path.join(__dirname, 'preload.js'),
},
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Open the DevTools.
mainWindow.webContents.openDevTools();
};
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
render.js
const { remote } = require('#electron/remote')
document.getElementById('close').onclick = function() {
console.log("debug")
var window = remote.getCurrentWindow();
window.close();
}
and html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Instapath</title>
<link rel="stylesheet" href="index.css" />
<script defer src="render.js"></script>
</head>
<body class="content">
<button id="close" style="position:fixed;">Close</button>
<div><h1>Hi!</h1></div>
</body>
</html>

while running JS app uncaught exception error require is not defined occurs [duplicate]

This question already has answers here:
Client on Node.js: Uncaught ReferenceError: require is not defined
(11 answers)
Closed 1 year ago.
i gone through a video link to create a simple java script based app using electron. https://www.youtube.com/watch?v=TnXz_nnQZrwI
While trying to create an app i got the following error even though i enable the nodeIntegration to true
index.html:12 Uncaught ReferenceError: require is not defined
at index.html:12
I don't know how to resolve it plz help
This is my js and Html files
my index.js file
const { app, BrowserWindow } = require('electron');
const os = require('os-utils');
const path = require('path');
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences:{
nodeIntegration: true
}
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Open the DevTools.
mainWindow.webContents.openDevTools();
os.cpuUsage(function(v){
console.log('CPU Usage (%): '+ v*100);
mainWindow.webContents.send('CPU',v*100);
console.log('Mem Usage (%): '+ os.freememPercentage()*100);
mainWindow.webContents.send('Mem',os.freememPercentage()*100);
console.log('Total Mem (GB): '+ os.totalmem()/1024);
mainWindow.webContents.send('Total-Mem',os.totalmem()/1024);
});
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.
my index.html file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h1>💖 Hello World!</h1>
<p>Welcome to your Electron application.</p>
<script>
const electron = require('electron');
const ipcRenderer = electron.ipcRenderer;
ipcRenderer.on('CPU',(event,data)=>{
console.log('CPU %' + data);
});
ipcRenderer.on('Mem',(event,data)=>{
console.log('Mem Usage %' + data);
});
ipcRenderer.on('Total-Mem',(event,data)=>{
console.log('Total Mem (GB)' + data);
});
</script>
</body>
</html>
For Electron >= 12, nodeIntegration: true won't work without contextIsolation: false.
https://www.electronjs.org/docs/breaking-changes#default-changed-contextisolation-defaults-to-true
Alternatively, if you do not want to take any security risks by setting nodeIntegration: true, you can make ipcRenderer available to your renderer process by creating a global variable in a "preload-file" that is called just before your renderer window is created.
In main.js create your main renderer window like this:
function createWindow () {
win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: false
}
})
win.loadFile('index.html')
}
The important part is preload: path.join(__dirname, 'preload.js').
In your preload.js you create a global variable ipcRenderer like this:
process.once('loaded', () => {
global.ipcRenderer = electron.ipcRenderer;
});
Then ipcRenderer can be used in your renderer process' html code just like that:
<script>
...
ipcRenderer.send(...);
...
</script>

How to grant permission to audio in electron app in Windows?

I'm trying to implement speech recognition into the electron application. The solution works in chrome browser, but does not work in electron. The application stops listening immediately - it probably has no microphone permission. How to grant permissions?
index.js
const electron = require('electron');
const url = require('url');
const path = require('path');
const { app, BrowserWindow, ipcMain } = electron;
let mainWindow;
ipcMain.on('close-me', (evt, arg) => {
app.quit()
})
app.on('ready', () => {
mainWindow = new BrowserWindow({
transparent: true,
frame: false,
webPreferences: {
nodeIntegration: true,
webviewTag: true
}
});
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'web/index.html'),
protocol: 'file',
slashes: true
}));
mainWindow.webContents.openDevTools();
mainWindow.setFullScreen(true);
});
index.html
<!doctype html>
<html lang="en">
<head>
<title></title>
<link rel="stylesheet" href="styles/style.css">
</head>
<body>
<div class="container">
<button id="rec"> rec</button>
<button id="endrec"> end</button>
</div>
<script src="scripts/speech.js"></script>
</body>
</html>
speech.js
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.lang = 'pl-PL';
const rec = document.querySelector('#rec');
const endrec = document.querySelector('#endrec');
recognition.onstart = function () {
console.log('I started');
}
recognition.onend = function () {
console.log('I finished');
}
recognition.onresult = function () {
console.log('Take what I recorded');
console.log(event);
const current = event.resultIndex;
const transcript = event.results[current][0].transcript;
console.log(transcript);
}
rec.addEventListener('click', () => {
recognition.start();
console.log('You clicked me');
})
endrec.addEventListener('click', () => {
recognition.stop();
})
I've also tried solutions with
webview.addEventListener('permissionrequest', function (e) {
if (e.permission === 'media') {
e.request.allow();
}
});
and
navigator.webkitGetUserMedia({ audio: true })
UPDATE
I found a reason to stop recognizing - error - network
I think you'll want to use the setPermissionRequestHandler on your session, like this:
const electron = require('electron');
const url = require('url');
const path = require('path');
const {
app,
BrowserWindow,
ipcMain,
session
} = electron;
let mainWindow;
ipcMain.on('close-me', (evt, arg) => {
app.quit()
})
app.on('ready', () => {
mainWindow = new BrowserWindow({
transparent: true,
frame: false,
webPreferences: {
nodeIntegration: true,
webviewTag: true
}
});
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'web/index.html'),
protocol: 'file',
slashes: true
}));
mainWindow.webContents.openDevTools();
mainWindow.setFullScreen(true);
session.fromPartition("default").setPermissionRequestHandler((webContents, permission, callback) => {
let allowedPermissions = ["audioCapture"]; // Full list here: https://developer.chrome.com/extensions/declare_permissions#manifest
if (allowedPermissions.includes(permission)) {
callback(true); // Approve permission request
} else {
console.error(
`The application tried to request permission for '${permission}'. This permission was not whitelisted and has been blocked.`
);
callback(false); // Deny
}
});
});
I've faced similar problem myself and found out that google doesn't provide speechAPI for CLI based apps like electron. Your best bet is to use either Google Cloud Speech API or any third-party API like Microsoft Cognitive Service.
Are you testing on MacOS? I faced a similar issue in my MBP, and below check solved the issue -
systemPreferences.askForMediaAccess(microphone)
See the Electron doc reference for additional details.

Electron.js Error: require is not defined

I'm writing my first electron app, and I was trying to show a window when a button is clicked. I have an error message:
Uncaught ReferenceError:
require is not defined
at dialog.js:2
I'm using the version "electron-nightly": "^6.0.0-nightly.20190213"
here is the code:
index.js:
const electron = require('electron');
const {app, BrowserWindow} = electron;
const path = require('path');
const url = require('url');
let win
function main(){
win = new BrowserWindow({ width: 500, height: 400});
win.loadURL(url.format( {
pathname: path.join(__dirname, './index.html'),
protocol: 'file',
slashes: true
} ));
win.webContents.openDevTools()
}
exports.openDialog = () => {
let dial = new BrowserWindow({ width: 400, height: 200});
dial.loadURL(url.format( {
pathname: path.join(__dirname, './dialog.html'),
protocol: 'file',
slashes: true
} ));
}
app.on('ready', main);
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello world</title>
</head>
<body>
<h1>Hello Electron!!</h1>
<button id="btn">Show dialog</button>
<script src="./dialog.js"></script>
</body>
</html>
dialog.js:
const index = require('electron').remote.require('./index.js'); //Error line: Uncaught ReferenceError: require is not defined at dialog.js:2
const button = document.getElementById('btn');
button.addEventListener('click', () => {
index.openDialog();
});
Is this error something about ES6+?
You may have to enable Node integration in your new window (disabled by default according to the documentation) :
index.js
function main() {
win = new BrowserWindow({
width: 500,
height: 400,
webPreferences: {
nodeIntegration: true
}
});
win.loadFile("index.html") // To load local HTML files easily
}

Trying to send data from one electron window to another via ipc

Building my first electron app and I'd like the workflow to be as follows:
mainWindow opens -> user clicks 'open' button -> 2nd window opens -> user enters input/hits submit -> mainWindow opens back up displaying user input
Below is my app.on('ready') from my main.js. The application startup (win.loadURL) works fine, as does the open-new-window event. The weirdness comes in the input-broadcast.
When the user enters input in the second window, the main window will re-open. However, the text in the console.log in the input-broadcast does not appear, and the input-received never fires in the main window's renderer.
Not sure what I'm doing wrong, however I may be using the wrong design pattern as well. Any help would be greatly appreciated!
main.js
const {app, BrowserWindow, ipcMain, remote} = require('electron');
const url = require('url');
const path = require('path');
const countdown = require('./countdown');
let win;
const windows = [];
app.on('ready', () =>{
console.log('app ready');
ipcMain.on('open-new-window', () =>{
console.log('trying to open window');
win.loadURL(url.format({
pathname: path.join(__dirname, 'enterValue.html'),
protocol: 'file:',
slashes: true
}));
});
ipcMain.on('input-broadcast', (evt, data) =>{
console.log('input-broadcast happened in main');
win.webContents.send('input-received', data);
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}));
});
win = new BrowserWindow({width: 800, height: 600});
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}));
win.on('closed', () =>{
console.log('closed');
win = null;
});
})
renderer.js (assoc. with the index.html)
console.log('from renderer1');
const {ipcRenderer} = require('electron');
document.getElementById('start').addEventListener('click', ()=>{
ipcRenderer.send('open-new-window');
console.log('window button clicked');
});
ipcRenderer.on('open-new-window', (evt, count) =>{
document.getElementById('userInput').innerHTML(count);
});
ipcRenderer.on('input-received', (evt, data) =>{
console.log('input received');
console.log(evt);
console.log(data);
});
renderer2.js (assoc. with the user enterValue.html)
console.log('from renderer2');
const {ipcRenderer} = require('electron');
document.getElementById('submitButton').addEventListener('click', (evt, input)=>{
var input = document.getElementById('randomInput').value;
ipcRenderer.send('input-broadcast', input);
});
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
<p>Your input was <span id="userInput"></span><p>
<button id="start">Open</button>
<script>require('./renderer')</script>
</html>
enterValue.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>Enter a name</p>
<input type="text" id="randomInput" placeholder="enter a value"/>
<button id="submitButton">Submit</button>
<script>require('./renderer2.js')</script>
</body>
</html>
Your call order is not right when sending input back to renderer.js. You call
win.webContents.send('input-received', data)
when index.html is not yet re-loaded into win!
To fix this you should swap the calls and make sure that the content is ready when you send ipc message
ipcMain.on('input-broadcast', (evt, data) => {
console.log('input-broadcast happened in main')
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
win.webContents.once('dom-ready', () => {
win.webContents.send('input-received', data)
})
})

Categories

Resources