window.webContents.send() causes memory leak - javascript

I'm experiencing an issue in Electron where window.webContents.send() behaves as expected on the first execution, but after I call it again the function runs twice, then three times, etc.
Here's a stripped back example of one of the menubar functions I'm using to tell the renderer to package data for saving.
Main.js
{
label: 'Save',
click() {
window.webContents.send('myChannel', myArgs);
}
}
Renderer.js
ipcRenderer.once('myChannel', (evt, myArgs) => {
// package data for saving
});
My understanding is that Electron is creating a new event handler each time I click save in the menubar. I can't seem to find any documentation on how to dispose the event handler in the electron docs.
Here's a link to a similar problem. The solution isn't of much help to me, as I need these functions to only be run when they're called from the menubar, not when the app first launches.
Thanks!

Related

How do I start streaming immediately after I started Jitsi API?

I have a Jitsi instance running in one of the pages of my Angular application. It works flawlessly.
Now I want a stream to start as soon as the API is initialized. I couldn't find any onLoad or onStart event of the API. So initially I tried this way:
this.api = new JitsiMeetExternalAPI("mydomain.com", this.options);
this.api.executeCommand('startRecording', {
mode: 'stream',
rtmpStreamKey: "MyKey",
rtmpBroadcastID: "MyId"
})
And it didn't work. After some fruitless search I've made it work moving execute command to a function and doing:
setTimeout(()=>this.startStream(), 10000);
But that's ugly and error-prone as hell. I imagine it should exist a better way .
How do I know that the API is fully initialized so I can start live stream ?
Edit
I tried onload event on API creation but it works only sometimes. Others it just ignores the command.

Best way to run some code only once on server start in Nuxt.js (and not during build)

While I wrote this answer for StackOverflow I came across the problem that I wanted to execute some code exactly once in Nuxt.js when the server is started (or while the server is starting).
I thought about writing a module or a plugin, but I did not succeed, since both were executed every time I contacted the server, i.e., every time I made a call to localhost:3000/myPage.
Probably I am missing the right module hook or some plugin setting?
Since I could not find any information on this problem in the official documentation, I now came up with a quite ugly solution: I wrote a serverMiddleware that executes some code (the code that should be run only once) and then returns an empty handler - which now adds (little) unnecessary overhead to every request.
My question: What would have been the best way to execute some code exactly once on a Nuxt.js server during/after startup, but not during building?
Minimal ugly working example:
nuxt.config.js:
export default {
...
serverMiddleware: [ "~/serverMiddleware/run-once.js" ]
...
}
~/serverMiddleware/run-once.js:
console.log("Yay, I only run once when the server is started!")
// Since we are a serverMiddleware, we have to return a handler, even if this it does nothing
// I think this is really ugly...
export default function (req, res, next) {
next()
}
PS: I saw questions such as Is it possible for Nuxt JS plugins to only run once? but it seems to not answer my question since the vue-renderer:ssr:prepareContext nuxt hook also executes every time I send a request to the server.
Also, a module such as the following does not work since it is also executed during nuxt build and not only on nuxt dev or nuxt start:
export default function MyModuleThatShouldOnlyRunOnce (_moduleOptions) {
console.log("I run on 'nuxt dev' and 'nuxt start', but sadly also on 'nuxt build' :(");
}
I don't know if this topic is still relevant, but you can solve this using a 'ready' hook:
First create a file like this (./hooks/hooks.js):
export default (nuxtConfig) => ({
ready: () => {
// Execute your code here
}
});
Then add it to your nuxt.config.js:
import hooks from './hooks/hooks';
export default {
// Other stuff
hooks: hooks(this),
// Other stuff
}

What is the proper way to restart an Electron app?

In this Electron documentation page, they recommend that to restart an application, one should execute app.quit or app.exit after the call to app.relaunch:
Note that this method does not quit the app when executed, you have to call app.quit or app.exit after calling app.relaunch to make the app restart.
However after experimenting I found that the order doesn't seem to actually matter. (See my example below.)
I know that app.quit and app.exit are not quite the same. The former can be interrupted and will trigger some events while the latter will force the app to exit without triggering any events or allowing the app to cancel the action.
Question: assuming that it is always ok to force the app to exit and that we don't have any tasks to perform before the app exits, is there:
A reason to prefer app.quit or app.exit?
A reason why one must run app.quit or app.exit after app.relaunch?
Here's a very simple Electron app:
package.json
{
"name": "burrito",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^4"
}
}
main.js
const {app, BrowserWindow, Menu} = require('electron');
let mainWindow;
app.on('ready', () => {
Menu.setApplicationMenu(
Menu.buildFromTemplate([
{role: 'appMenu', submenu: [
{label: 'relaunch(); exit()', click() {
app.relaunch();
app.exit();
}},
{label: 'relaunch(); quit()', click() {
app.relaunch();
app.quit();
}},
{type: 'separator'},
{label: 'exit(); relaunch()', click() {
app.exit();
app.relaunch();
}},
{label: 'quit(); relaunch()', click() {
app.quit();
app.relaunch();
}}
]}
])
);
mainWindow = new BrowserWindow({width: 640, height: 480});
mainWindow.loadFile('index.html');
});
Producing the following application menu:
A click on any of the menu item will produce the same result: the app quits then restarts.
The proper way to restart an electron app is:
app.relaunch()
app.exit()
See official documentation.
app.relaunch
According to app.relaunch docs:
Relaunches the app when current instance exits.
(...)
Note that this method does not quit the app when executed, you have to call app.quit or app.exit after calling app.relaunch to make the app restart.
When app.relaunch is called for multiple times, multiple instances will be started after current instance exited.
We can assume that:
Calling app.relaunch() only won't do anything (until the user closes the application, then it will restart);
You can call app.quit() or app.exit() in order to close the application, then it will restart because you already called app.relaunch().
app.quit
Citing the docs again:
Try to close all windows. The before-quit event will be emitted first. If all windows are successfully closed, the will-quit event will be emitted and by default the application will terminate.
This method guarantees that all beforeunload and unload event handlers are correctly executed. It is possible that a window cancels the quitting by returning false in the beforeunload event handler.
It means that using app.quit() may or may not terminate the application.
app.exit
The docs states:
All windows will be closed immediately without asking the user, and the before-quit and will-quit events will not be emitted.
So, immediately is a dangerous word. It means that the app will be closed as soon as it is possible, and that it certainly will close, but not instantly.
Should I use app.quit or app.exit?
Both are valid, depends on your use case:
If your user may be on a screen where you have some validations to prevent they from closing the app because of reasons, app.quit is probably better for you. Just be careful to not call app.relaunch more than once (it causes multiple instances to be started after exiting the current instance):
app.relaunch();
app.quit(); // maybe the application will be closed; maybe not
If you need (or want) to close the app immediately in order to apply some setting, for example, no matter what is happening in that moment, you should call app.exit. Doing it you are safe that the app will be closed and relaunched:
app.relaunch();
app.exit(); // the application will be closed as soon as possible
Why should I call app.relaunch first?
Well, because it is logical. See the code below:
app.exit();
app.relaunch();
You're telling: "Hey, Electron, please close my app. Oh, and restart it after closing.". It'll work most of the times, but only because app.exit is slower than app.relaunch to execute. They're not running synchronously.
If, for some reason, Electron terminates your application before knowing it should be relaunched, it would be an unexpected behavior for you, but that's what you told Electron to do.
quit gracefully closes all the windows then exits, compared to exit which simply terminates the application with no regard to anything else, like process.exit in Node. You'll want to use quit in most situations for safety.
It is preferred to call relaunch first to prevent race conditions. This will almost never happen in production because of how the event loop works, but it's just good practice.

React Native (iOS): RCTEventEmitter before javascript is loaded

I have a problem implementing beacons in my app. I am using the library react-native-beacons-manager, but I think is a general "problem".
The issue is that when I kill my app (and this is important to reproduce the issue) and I get closer to my beacon, iOS fire an event regionDidEnter that is caught by a file wrote in native code, and then, sent to javascript using the method of RCTEventEmitter: [self sendEventWithName:#"regionDidEnter" body:event];
The problem is that this event is fired before javascript is fully loaded, so my listener:
// component.js
Beacons.BeaconsEventEmitter.addListener('regionDidEnter', b => {
//code
});
doesn't get called.
Order of events:
[BeaconsDemo] Did finish launching enter
[BeaconsDemo] Did finish launching After jsBundleURLForBundleRoot
[BeaconsDemo] Did finish launching After RCTRootView alloc
[BeaconsDemo] Did finish launching After UIWindow alloc
[BeaconsDemo] Did finish launching After makeKeyAndVisible
[BeaconsDemo] Did finish launching end
--iOS send the event and it is caught by RNiBeacon but it has no listeners yet--
[BeaconsDemo] no listeners in RnIBeacon.m
--Register
[BeaconsDemo] regionDidExit
-- First line of javascript --
[BeaconsDemo] start observing
[BeaconsDemo] requestAlwaysAuth
Any idea to handle this situation? Is there any way or approach to send the event through RCTEventEmitter waiting for the javascript is loaded?
Thanks
This general problem also exists when writing native beacon apps for iOS or Android. The solution is that you must set up your "hook" that enables beacon monitoring and adds the event listener (or delegate / notification callback as it is called in native code) in the appropriate place per platform:
iOS: AppDelegate.didFinishLanching(options: )
Android: Application.onCreate()
The key is that this setup must be complete before those methods return.
This same rule applies for ReactNative. The trick with ReactNative, is that by default JavaScript does not run on these events -- it runs only when a screen is launched, which sets up the hook too late for the above to work when your app is killed. To get this to work, you'll need to eject your app so you can set up some custom native code in the above callbacks.
Two options:
Implement beacon detection natively (easiest, but requires native coding on a per-platform basis)
Add native code in the above native callbacks that starts a RCTBridge on iOS, and launches a view that executes code that triggers our JavaScript code to set up beacon detection. On Android, the equivalent would be to construct a new ReactRootView and ReactNativeInstanceManager in a way that it triggers your JavaScript code to set up beacon detection.
I have not personally tested option 2 to see if it can set up the hooks soon enough. If it works, it will certainly be harder than the native solution, but allows you to keep your beacon detection logic in JavaScript.
(https://github.com/MacKentoch/react-native-beacons-manager/issues/50)
I've forked #newoceaninfosys' fork and added the 'missed beacon' method. Check my last 3 commits for how to replicate it.
(https://github.com/iamandiradu/react-native-beacons-manager)
Use it by adding this in your didMount function:
if (Platform.OS === 'ios') {
// iOS cold start listener
this.beaconMissedListener = Beacons.BeaconsEventEmitter.addListener(
'onMissedBeacon',
data => {
if (data) {
this._beaconListener(data);
}
},
);
Beacons.getMissedBeacon();
}
This will retrieve the data that got 'lost' because the event triggered faster than the listener.
(React Native (iOS): RCTEventEmitter before javascript is loaded)
Hope this helps someone. :)

How to know if service worker was updated in gatsby-plugin-offline

I've installed gatsby-plugin-offline, It works fine, but I want to listen for sw update event so I can notify user that new version of app is available.
Prior to this I used offline-plugin Which I speculate is behinde gatsby's plugin? They have doc explaining how to achieve what I want here: https://github.com/NekR/offline-plugin/blob/master/docs/updates.md but I can't figure out how to get these events via gatsby, any suggestions guys?
Currently gatsby-plugin-offline is a wrapper around sw-precache, and doesn't provide any direct hooks into much beyond the caching settings shown in the config options. It looks like there are a few ways around this via sw-precache, so it might be worth working on a PR or feature request over on the gatsby issues page.
I was looking for exactly the same answer.
There is an event you can hook into called "onServiceWorkerUpdateFound".
Just create (if you don't have already) a gatsby-browser.js file and do something like this.
gatsby-browser.js
exports.onServiceWorkerUpdateFound = () => {
// do something
};
I created a <div> that shows a "new version available" message with an onClick event that reloads the page (this then will activate the new service worker).
More Information: Gatsby Browser APIs

Categories

Resources