- Notifications
You must be signed in to change notification settings - Fork52
DEPRECATED: Execute JavaScript in remote Electron processes, but more betterer
License
electron-userland/electron-remote
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This project is no longer maintained, pull requests are no longer being reviewed or merged and issues are no longer being responded to.
electron-remote provides an alternative to Electron'sremote
module based around Promises instead of synchronous execution. It also provides an automatic way to use BrowserWindows as "background processes" that auto-scales based on usage, similar to Grand Central Dispatch or the .NET TPL Taskpool.
import{createProxyForMainProcessModule}from'electron-remote';// app is now a proxy for the app module in the main processconstapp=createProxyForMainProcessModule('app');// The difference is all methods return a Promise instead of blockingconstmemoryInfo=awaitapp.getAppMemoryInfo();
import{createProxyForRemote}from'electron-remote';// myWindowJs is now a proxy object for myWindow's `window` global objectconstmyWindowJs=createProxyForRemote(myWindow);// Functions suffixed with _get will read a valueuserAgent=awaitmyWindowJs.navigator.userAgent_get()
import{requireTaskPool}from'electron-remote';constmyCoolModule=requireTaskPool(require.resolve('./my-cool-module'));// This method will run synchronously, but in a background BrowserWindow process// so that your app will not blockletresult=awaitmyCoolModule.calculateDigitsOfPi(100000);
Remote is super convenient! But it also has some downsides - its main downside is that its action issynchronous. This means that both the main and window processes willwait for a method to finish running. Even for quick methods, calling it too often can introduce scroll jank and generally cause performance problems.
electron-remote is a version of remote that, while less ergonomic, guarantees that it won't block the calling thread.
createProxyForRemote
is a replacement for places where you would use Electron'sexecuteJavaScript
method on BrowserWindow or WebView instances - however, it works a little differently. Using a new feature in ES2015 calledproxy objects, we create an object which represents thewindow
object on a remote context, and all method calls get sent as messages to that remote instead of being run immediately, which feels very similar to theremote
Electron module.
This provides a number of very important advantages:
createProxyForRemote
uses asynchronous IPC instead of blocking- Parameters are serialized directly, so you don't have to try to build strings that can be
eval
d, which is a dangerous endeavor at best. - Calling methods on objects is far more convenient than trying to poke at things via a remote eval.
Astute observers will note, that getting the value of a property is always a synchronous operation - to facilitate that, any method with_get()
appended to it will let you fetch the value for the property.
import{createProxyForRemote}from'electron-remote';// myWindowJs is now a proxy object for myWindow's `window` global objectconstmyWindowJs=createProxyForRemote(myWindow);// Functions suffixed with _get will read a valuemyWindowJs.navigator.userAgent_get().then((agent)=>console.log(`The user agent is${agent}`));
Before you usecreateProxyForRemote
, youmust callinitializeEvalHandler()
in the target window on startup. This sets up the listeners that electron-remote will use.
// In my window's main.jsinitializeEvalHandler();window.addNumbers=(a,b)=>a+b;// In my main processletmyWindowProxy=createProxyForRemote(myWindow);myWindowProxy.addNumbers(5,5).then((x)=>console.log(x));>>>10
This is meant to be a drop-in replacement for places you would have usedremote
in a renderer process. It's almost identical tocreateProxyForRemote
, but instead ofeval
ing JavaScript it can only call methods on main process modules. It still has all the same benefits: asynchronous IPC instead of anipc.sendSync
.
electron-remote has a number of significant caveats versus the remote module that you should definitely be aware of:
- Remote values must be Serializable
Objects that you return to the calling process must be serializable (i.e. you can callJSON.stringify
on it and get a valid thing)- this means that creating Classes won't work, nor will return objects like BrowserWindows or other Electron objects. For example:
letmyWindowProxy=createProxyForRemote(myWindow);// XXX: BAD - HTML elements aren't serializableletobj=myWindowProxy.document.createElement('h1');
- Remote event listeners aren't supported
Anything that involves an event handler isn't going to work:
// XXX: BAD - You can't add event handlersmyWindowProxy.document.addEventListener('onBlur',(e)=>console.log("Blur!"));
Renderer Taskpools provide an automatic way to use BrowserWindows as "background processes" that auto-scales based on usage, similar to Grand Central Dispatch or the .NET TPL Taskpool. This works by allowing you to provide a Module that you'd like to load in the remote processes, which will be loaded and unloaded on the fly according to demand.
Let's look at the example again:
import{requireTaskPool}from'electron-remote';constmyCoolModule=requireTaskPool(require.resolve('./my-cool-module'));// This method will run synchronously, but in a background BrowserWindow process// so that your app will not blockletresult=awaitmyCoolModule.calculateDigitsOfPi(100000);
By default,requireTaskPool
will create up to four background processes to concurrently run JS code on. As these processes become busy, requests will be queued to different processes and wait in line implicitly.
SincerequireTaskPool
will create and destroy processes as needed, this means that global variables or other state will be destroyed as well. You can't rely on setting a global variable and having it persist for a period of time longer than one method call.
One module that is super useful to have from the main process is a way to make network requests using Chromium's networking stack, which correctly does things such as respecting the system proxy settings. To this end, electron-remote comes with a convenient wrapper around Rx-DOM's AJAX methods calledremote-ajax
.
import{requireTaskPool}from'electron-remote';constremoteAjax=requireTaskPool(require.resolve('electron-remote/remote-ajax'));// Result is the object that XmlHttpRequest gives youletresult=awaitremoteAjax.get('https://httpbin.org/get');console.log(result.url)>>>'https://httpbin.org/get'
See the documentation forRx-DOM for how these methods work.
Another method that is included isdownloadFileOrUrl
, which lets you download a file to a target:
/** * Downloads a path as either a file path or a HTTP URL to a specific place * *@param {string} pathOrUrl Either an HTTP URL or a file path. *@return {string} The contents as a UTF-8 decoded string. */functiondownloadFileOrUrl(pathOrUrl,target)
About
DEPRECATED: Execute JavaScript in remote Electron processes, but more betterer
Resources
License
Code of conduct
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Contributors5
Uh oh!
There was an error while loading.Please reload this page.