Electron: Race condition between main and renderer process - node.js

In my Electron application, I am seeing weird behavior. In Windows, sometimes the renderer process executes before the initialization of Electron finishes, which is causing the issue in a startup.
For eg: I set up a sequelize database and register IPC channels in the constructor of Main.ts file, so as per my knowledge, app.on('ready') event should be fired once the constructor finishes execution but sometimes in Windows OS only, ready events fires even before the database setup, and my renderer process is calling the database to fetch the default records for the MainWindow.
I think this is a race condition between the renderer process and main process execution, does anyone know how to fix that?
Main.ts
export class Main {
private mainWindow: BrowserWindow;
static instance: Main;
public async init(ipcChannels: IpcChannelInterface[]) {
Main.instance = this;
// Registering the IPC Channels
await this.registerIpcChannels(ipcChannels);
var config = require('../../package.json');
app.setAsDefaultProtocolClient(config.build.protocols.name);
app.setAppUserModelId(config.build.appId);
app.on('ready', Main.createWindow);
app.on('window-all-closed', Main.onWindowAllClosed);
app.on('activate', Main.onActivate);
//Below statement setup the database
await SequelizeDB.setup();
}
}
(new Main()).init([new IpcChannel1(), new IpcChannel2()]);

The ready event fires whenever the Electron setup has finished. It has nothing to do with your constructor or init method. From docs:
Emitted once, when Electron has finished initializing
It sounds like you're saying that your createWindow function has a dependency on the database setup function. In that case, you can just do the setup first:
await SequelizeDB.setup();
await app.whenReady(); // this can replace your on("ready", ...) stuff
Main.createWindow();

Related

Electron: Using a module in the main process

I'm trying to use a module I made myself in the main process in Electron,
but for some reason it doesn't work as intended (at all).
In the main process (main.js), I define the module
const connection = require('connection');
That module exports a function called init
var Connection = {
init: function() {
...
},
....
}
module.exports = Connection;
But when trying to call this method, through the main process (main.js) on a webpage. (login.html)
var Connection = require('electron').remote.connection;
Connection.init();
It tells me that Connection is undefined.
I know the Connection module I made works, because I've used it just fine in the renderer process.
The reason that I want to use the entire Connection module in the main process, is so that I could keep that connection alive and performing tasks even when the user goes to another page.
I've searched all around but can't seem to find the solution to my problem.
Thank you.
Found the answer,
the proper way to use a module through the main process would be to use this:
require('electron').remote.require('connection');

How do I test child processes using chai and mocha?

I'm creating a framework to execute processes at a specific time (cron-like) and to test it I'm using chai-mocha-grunt.
The architecture of solution is based on this example. Basically, we have:
A Master process, which calls the Child (via child_process.fork) a specific number of times.
A Child process, which executes something using setInverval();
A process to call the Master.start() function.
With this architecture how do I test to ensure that threads are executed at the correct time using mocha and chai (with the 'assert' library)?
In other words, how do I make chai 'listen' to the threads and check if they are executed at the correct time?
I'm not sure you need chai itself to listen to your threads. If you're building off of the example you linked this should be pretty straight forward because the Master.js is already an EventEmitter and it's already emitting all events it hears from the child processes.
Your test structure could be as simple as this:
describe('ForkExample test', function() {
// Set an appropriate test timeout here
this.timeout(1000);
it('should do stuff at the right time', function(done) {
var fe = new ForkExample();
fe.start(1);
fe.on('event', function(type, pid, e) {
if (type === 'child message') {
// Check here that the timing was within some expected range
done();
}
});
});
});

Titanium: Different execution contexts are not multi-threaded?

I am trying to use titanium execution contexts to produce parallel code execution between the main application context and others. I am using CreateWindow with a url property refers to a .js file inside "lib" folder. But by logging the execution on both iOS and Android devices it seems that different contexts are executed on the app main thread, no parallelism here.
My new context trigger inside my Alloy controller:
var win2 = Ti.UI.createWindow({
title: 'New Window',
url: 'thread.js',
backgroundColor:'#fff'
});
win2.open();
Ti.API.log('after open');
My thread.js contents:
Ti.API.log("this is the new context");
Ti.App.fireEvent("go" , {});
while(true)
{
Ti.API.log('second context');
}
This while loop apparently blocks the main context (my Alloy controller) waiting it to exit.
Any suggestions of how can I execute some code (mainly heavy sqlite db access) in background so that the UI be responsive? (Web workers are not a choice for me).
You could try to achieve the wanted behaviour with a setInterval() or setTimeout() method.
setInterval()[source]:
function myFunc() {
//your code
}
//set the interval
setInterval(myFunc,2000) //this will run the function for every 2 sec.
Another suggested method would be to fire a custom event when you need the background behavior since it is processed in its own thread. This is also suggested in the official documentation.
AFAIK, titanium is single threaded, because JavaScript is single threaded. You can get parallel execution with native modules, but you'll have to code that yourself for each platform.
Another option is to use web workers, but I consider that to be a hack.

Nodejs event handling

Following is my nodejs code
var emitter = require('events'),
eventEmitter = new emitter.EventEmitter();
eventEmitter.on('data', function (result) { console.log('Im From Data'); });
eventEmitter.on('error', function (result) { console.log('Im Error'); });
require('http').createServer(function (req, res) {
res.end('Response');
var start = new Date().getTime();
eventEmitter.emit('data', true);
eventEmitter.emit('error', false);
while(new Date().getTime() - start < 5000) {
//Let me sleep
}
process.nextTick(function () {
console.log('This is event loop');
});
}).listen(8090);
Nodejs is single threaded and it runs in an eventloop and the same thread serves the events.
So, in the above code on a request to my localhost:8090 node thread should be kept busy serving the request [there is a sleep for 5s].
At the same time there are two events being emitted by eventEmitter. So, both these events must be queued in the eventloop for processing once the request is served.
But that is not happening, I can see the events being served synchronously as they are emitted.
Is that expected? I understand that if it works as I expect then there would be no use of extending events module. But how are the events emitted by eventEmitter handled?
Only things that require asynchronous processing are pushed into the event loop. The standard event emitter in node will dispatch an event immediately. Only code using things like process.nextTick, setTimeout, setInterval, or code explicitly adding to it in C++ affect the event loop, like node's libraries.
For example, when you use node's fs library for something like createReadStream, it returns a stream, but opens the file in the background. When it is open, node adds to the event loop and when the function in the loop gets called, it will trigger the 'open' event on the stream object. Then, node will load blocks from the file in the background, and add to the event loop to trigger data events on the stream.
If you wanted those events to be emitted after 5 seconds, you'd want to use setTimeout or put the emit calls after your busy loop.
I'd also like to be clear, you should never have a busy loop like that in Node code. I can't tell if you were just doing it to test the event loop, or if it is part of some real code. If you need more info, please you expand on the functionality you are looking to achieve.

Networking without blocking ui in Qt 4.7

I have a server to which multiple clients can connect to. The client is GUI while the server is command line. The client has several functions (such as connect and login) which, when sent to the server should receive a reply.
Basically I need to run the QTcpSocket functions waitForConnection and waitForReadyRead. However, I need to do this without blocking the UI.
What I thought of doing was the following:
Have a class (Client) implement QThread which does all the waiting. This is created in main.
Client::Client (...)
{
moveToThread (this); // Not too sure what this does
mClient = new QTcpSocket (this);
start();
}
void Client::run (void)
{
exec();
}
void Client::connectToServer (...)
{
mClient->connectToHost (hostname, port);
bool status = mClient->waitForConnected (TIMEOUT);
emit connected (status);
}
void Client::login (...)
{
... Similar to connectToServer ...
}
Then the GUI (for example, ConnectToServerDialog) I run this whenever I am ready to make a connection. I connect the "connected signal" from the thread to the dialog so when I am connected or connection timed out it will emit this signal.
QMetaObject::invokeMethod (mClient, "connectToServer", Qt::QueuedConnection,
Q_ARG (const QString &, hostname), Q_ARG (quint16, port));
I am getting an assert failure with this (Cannot send events to objects owned by a different thread.) Since I am fairly new to Qt I don't know if what I am doing is the correct thing.
Can somebody tell me if what I am doing is a good approach and if so why is my program crashing?
The best thing is never to call methods like waitForBlah() ... forcing the event loop to wait for an undetermined period introduces the possibility of the GUI freezing up during that time. Instead, connect your QTcpSocket's connected() signal to some slot that will update your GUI as appropriate, and let the event loop continue as usual. Do your on-connected stuff inside that slot.
I don't recommend start thread in constructor.
Initialize it like:
Client * client = new Client();
client->moveToThread(client);
client->start();
Or if you don't want to use such solution, add in constructor before start(); line this->moveToThread(this);
upd: sorry, i didn't saw at first time, that you have this string.

Resources