Merge pull request #147 from atom/remote-docs
Revise the docs on remote module
This commit is contained in:
commit
19a35b58f0
2 changed files with 111 additions and 37 deletions
|
@ -309,6 +309,10 @@ visible page.
|
||||||
You can write received `image` directly to a `.png` file, or you can base64
|
You can write received `image` directly to a `.png` file, or you can base64
|
||||||
encode it and use data URL to embed the image in HTML.
|
encode it and use data URL to embed the image in HTML.
|
||||||
|
|
||||||
|
**Note:** Be sure to read documents on remote buffer in
|
||||||
|
[remote](../renderer/remote.md) if you are going to use this API in renderer
|
||||||
|
process.
|
||||||
|
|
||||||
### BrowserWindow.getPageTitle()
|
### BrowserWindow.getPageTitle()
|
||||||
|
|
||||||
Returns the title of web page.
|
Returns the title of web page.
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
# remote
|
# remote
|
||||||
|
|
||||||
It's common that the developers want to use modules in browsers from the
|
The `remote` module provides a simple way to do inter-process communication
|
||||||
renderer, like closing current window, opening file dialogs, etc. Instead of
|
between renderer process and browser process.
|
||||||
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.
|
|
||||||
|
|
||||||
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
|
```javascript
|
||||||
var remote = require('remote');
|
var remote = require('remote');
|
||||||
|
@ -15,31 +20,50 @@ var win = new BrowserWindow({ width: 800, height: 600 });
|
||||||
win.loadUrl('https://github.com');
|
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
|
## Lifetime of remote objects
|
||||||
|
|
||||||
Every object returned by `remote` module represents an object in browser (e.g.
|
Atom-shell makes sure that as long as the remote object in renderer process
|
||||||
a remote object), so when you call methods of an object, or call a returned
|
lives (in other words, has not been garbage collected), the corresponding object
|
||||||
function, or even create a object with the returned constructor, you are
|
in browser process would never be released. And when the remote object has been
|
||||||
indeed making a synchronous RPC call. And when the renderer releases the last
|
garbage collected, the corresponding object in browser process would be
|
||||||
reference to the remote object, the browser would release the corresponding
|
dereferenced.
|
||||||
reference too.
|
|
||||||
|
|
||||||
This also means that, if the renderer keeps a reference to an object in
|
But it also means that, if the remote object is leaked in renderer process, like
|
||||||
browser, the object would never be released. So be careful to never leak the
|
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.
|
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 to browser
|
||||||
passing callbacks when calling remote functions, and the callbacks passed
|
|
||||||
would become remote functions in the browser.
|
|
||||||
|
|
||||||
But in order to avoid possible dead locks, the callbacks passed to browser
|
Some APIs in browser process accepts callbacks, and it would be attempting to
|
||||||
would be called asynchronously in browser, so you should never expect the
|
pass callbacks when calling a remote function. Yes `remote` module does support
|
||||||
browser to get the return value of the passed callback.
|
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
|
First, in order to avoid dead locks, the callbacks passed to browser process
|
||||||
very tempting to do things like following:
|
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
|
```javascript
|
||||||
var remote = require('remote');
|
var remote = require('remote');
|
||||||
|
@ -48,35 +72,81 @@ remote.getCurrentWindow().on('close', function() {
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Yes it will work correctly, but when you reload the window, the callback you
|
But the callback would be stored in the browser process persistently until you
|
||||||
setup on the object in browser will not be erased, resources are leaked and
|
explicitly uninstall it! So each time you reload your window, the callback would
|
||||||
there is no magic in javascript to release a referenced object.
|
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
|
So generally, unless you are clear what you are doing, you should always avoid
|
||||||
write the callback in browser and send messages to renderer. And also make use
|
passing callbacks to browser process.
|
||||||
of DOM's events like `unload` and `beforeunload`, they will work perfectly.
|
|
||||||
|
## Remote buffer
|
||||||
|
|
||||||
|
An instance of node's `Buffer` is an object, so when you got a `Buffer` from
|
||||||
|
browser process, what you got was indeed a remote object (let's call it remote
|
||||||
|
buffer), and everything would just follow the rules of remote objects.
|
||||||
|
|
||||||
|
However you should remember that though a remote buffer behaves like the real
|
||||||
|
`Buffer`, it's not a `Buffer` at all. If you pass a remote buffer to node APIs
|
||||||
|
that accepting `Buffer`, you should assume the remote buffer would be treated
|
||||||
|
like a normal object, instead of a `Buffer`.
|
||||||
|
|
||||||
|
For example you can call `BrowserWindow.capturePage` in renderer process, which
|
||||||
|
returns a `Buffer` by calling passed callback:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var remote = require('remote');
|
||||||
|
var fs = require('fs');
|
||||||
|
remote.getCurrentWindow().capturePage(function(buf) {
|
||||||
|
fs.writeFile('/tmp/screenshot.png', buf, function(err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
But you may be surprised to find that the file written was corrupted. This is
|
||||||
|
because when you called `fs.writeFile`, you thought `buf` was a `Buffer`, but
|
||||||
|
indeed it was a remote buffer, and it would be converted to string before it was
|
||||||
|
written to file. Since `buf` contained binary data and could not be represented
|
||||||
|
by UTF-8 encoded string, the written file would be corrupted.
|
||||||
|
|
||||||
|
The workaround is to write the `buf` in browser process, where it is a real
|
||||||
|
`Buffer`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var remote = require('remote');
|
||||||
|
remote.getCurrentWindow().capturePage(function(buf) {
|
||||||
|
remote.require('fs').writeFile('/tmp/screenshot.png', buf, function(err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The same thing could happen for all native types, but usually it would just
|
||||||
|
throw a type error. The `Buffer` deserves your special attention because it
|
||||||
|
can be converted to string and APIs accepting `Buffer` usually accept string
|
||||||
|
too, and data corruption only happens when it contains binary data.
|
||||||
|
|
||||||
## remote.require(module)
|
## remote.require(module)
|
||||||
|
|
||||||
* `module` String
|
* `module` String
|
||||||
|
|
||||||
Return a module in browser.
|
Returns the object returned by `require(module)` in the browser process.
|
||||||
|
|
||||||
## remote.getCurrentWindow()
|
## remote.getCurrentWindow()
|
||||||
|
|
||||||
Return the `BrowserWindow` object that represents current window.
|
Returns the [BrowserWindow](../browser/browser-window.md) object which
|
||||||
|
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.
|
|
||||||
|
|
||||||
## remote.getGlobal(name)
|
## remote.getGlobal(name)
|
||||||
|
|
||||||
* `name` String
|
* `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
|
## 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.
|
`remote.getGlobal('process')` but gets cached.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue