diff --git a/docs/api/renderer/remote.md b/docs/api/renderer/remote.md index 74117687cafe..48ac206289d5 100644 --- a/docs/api/renderer/remote.md +++ b/docs/api/renderer/remote.md @@ -1,12 +1,17 @@ # remote -It's common that the developers want to use modules in browsers from the -renderer, like closing current window, opening file dialogs, etc. Instead of -writing IPC code for every operation you want to do, atom-shell provides the -`remote` module to let you do RPC call just like using normal javascript -objects. +The `remote` module provides a simple way to do inter-process communication +between renderer process and browser process. -An example of creating a window in renderer: +In atom-shell, all GUI related modules are only available in the browser +process, if users want to call an browser side API in the renderer process +, they usually would have to explicitly send inter-process messages to the +browser process. But with the `remote` module, users can invoke methods of +objects living in browser process without sending inter-process messages +directly, like Java's +[RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation). + +An example of creating a browser window in renderer process: ```javascript var remote = require('remote'); @@ -15,31 +20,50 @@ var win = new BrowserWindow({ width: 800, height: 600 }); win.loadUrl('https://github.com'); ``` +## Remote objects + +Each object (including function) returned by `remote` module represents an +object in browser process (we call it remote object or remote function), when +you invoke methods of a remote object, or call a remote function, or even create +a new object with the remote constructor (function), you are actually sending +synchronous inter-process messages. + +In the example above, both `BrowserWindow` and `win` were remote objects. And +`new BrowserWindow` didn't create a `BrowserWindow` object in renderer process, +instead it created a `BrowserWindow` object in browser process, and returned the +corresponding remote object in renderer process, namely the `win` object. + ## Lifetime of remote objects -Every object returned by `remote` module represents an object in browser (e.g. -a remote object), so when you call methods of an object, or call a returned -function, or even create a object with the returned constructor, you are -indeed making a synchronous RPC call. And when the renderer releases the last -reference to the remote object, the browser would release the corresponding -reference too. +Atom-shell makes sure that as long as the remote object in renderer process +lives (in other words, has not been garbage collected), the corresponding object +in browser process would never be released. And when the remote object has been +garbage collected, the corresponding object in browser process would be +dereferenced. -This also means that, if the renderer keeps a reference to an object in -browser, the object would never be released. So be careful to never leak the +But it also means that, if the remote object is leaked in renderer process, like +being stored in a map but never got freed, the corresponding object in browser +process would also be leaked too. So you should be very careful not to leak remote objects. -## Passing callbacks +Primary value types like strings and numbers, however, are sent by copy. -Many APIs in browser accepts callbacks, so the `remote` module also supports -passing callbacks when calling remote functions, and the callbacks passed -would become remote functions in the browser. +## Passing callbacks to browser -But in order to avoid possible dead locks, the callbacks passed to browser -would be called asynchronously in browser, so you should never expect the -browser to get the return value of the passed callback. +Some APIs in browser process accepts callbacks, and it would be attempting to +pass callbacks when calling a remote function. Yes `remote` module does support +doing this, but you should also be extremely careful on this. -Another thing is the lifetime of the remote callbacks in browser, it might be -very tempting to do things like following: +First, in order to avoid dead locks, the callbacks passed to browser process +would be called asynchronously, so you should not expect the browser process to +get the return value of the passed callbacks. + +Second, the callbacks passed to browser process would not get released +automatically after they were called, instead they would persistent until the +browser process garbage collected them. + +For example, following code seems innocent at first glance, It installed a +callback for the `close` event on a remote object: ```javascript var remote = require('remote'); @@ -48,35 +72,34 @@ remote.getCurrentWindow().on('close', function() { }); ``` -Yes it will work correctly, but when you reload the window, the callback you -setup on the object in browser will not be erased, resources are leaked and -there is no magic in javascript to release a referenced object. +But the callback would be stored in the browser process persistently until you +explicitly uninstall it! So each time you reload your window, the callback would +be installed for once and previous callbacks were just leak. To make things +worse, since the context of previously installed callbacks have been released, +when `close` event was emitted exceptions would happen in browser process. -So if you really need to keep a reference of callbacks in browser, you should -write the callback in browser and send messages to renderer. And also make use -of DOM's events like `unload` and `beforeunload`, they will work perfectly. +So generally, unless you are clear what you are doing, you should always avoid +passing callbacks to browser process. ## remote.require(module) * `module` String -Return a module in browser. +Returns the object returned by `require(module)` in the browser process. ## remote.getCurrentWindow() -Return the `BrowserWindow` object that represents current window. - -`Note:` it doesn't return the `window` object which represents the global -scope, instead it returns an instance of the `BrowserWindow` class which is -created with `browser-window` module in browser. +Returns the [BrowserWindow](../browser/browser-window.md) object which +represents current window. ## remote.getGlobal(name) * `name` String -Return the `global[name]` value in browser. +Returns the global variable of `name` (e.g. `global[name]`) in the browser +process. ## remote.process -Getter to return the `process` object in browser, this is the same with +Returns the `process` object in the browser process, this is the same with `remote.getGlobal('process')` but gets cached.