Electronでipcを使ってプロセス間通信を行う

  • 108
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

概要

Electron(旧称atom-shell)には起動時に立ち上がるJavaScript側のプロセス(メインプロセス)と、メインプロセスから立ち上げるBrowserWindowのプロセス(レンダラプロセス)が存在する。メインプロセスとレンダラプロセスは別物なので、これらの間で状態を伝達する仕組みが必要になることがある。ElectronにもIPC(プロセス間通信)の仕組みは存在し、ずばりipcモジュールとして定義されている。

前提

BrowserWindow(レンダラプロセス)を立ち上げてHTMLを表示する部分までは終了しているものとする。

var app = require('app');
var BrowserWindow = require('browser-window');

app.on('ready', function() {
  var currentWindow = new BrowserWindow({});
  currentWindow.loadUrl('file://' + __dirname + '/index.html');
});

だいたいこれぐらいの環境を想定。

ipcを使う

レンダラプロセス(送信側)

var ipc = require('ipc');

// 非同期
ipc.send('asynchronous-message', 'ping');

// 同期
var response = ipc.sendSync('synchronous-message', 'ping');

sendSyncを使えば即座にメインプロセスからのレスポンスが取れるが、レスポンスを返すまでレンダラプロセスがブロックされるので、利用は非推奨となっている。

メインプロセス(受信側)

var ipc = require('ipc');

// 非同期
ipc.on('asynchronous-message', function(event, arg) {
  event.sender.send('asynchronous-reply', 'pong');  // 送信元へレスポンスを返す
});

// 同期
ipc.on('synchronous-message', function(event, arg) {
  event.returnValue = 'pong';  // 送信元へレスポンスを返す
});

ipcモジュールの実態はEventEmitterなので、同期非同期に関わらずonで受けられる。送信は非同期だったのに同期でレスポンスを返してしまった場合は、無効なレスポンスとして無視される。同期で送信して非同期でレスポンスを返した場合は、処理の終了を待った上で非同期レスポンスとして処理される。

非同期レスポンスはレンダラプロセスにてonで指定すれば受けられる。

WebContents.send

メインプロセスからレンダラプロセスへ送信を行う場合、WebContents.sendで送ることができる。

current.webContents.on('did-finish-load', function() {
  current.webContents.send('asynchronous-message', 'ping');
});

同期通信はデッドロックが発生しやすいという理由により存在しない。内部的にはipcの呼び出しなので、レンダラプロセスにおけるipcのレスポンス処理と同様に、onで指定することにより受けられる。

このときレンダラプロセスでJavaScriptの実行が完了していないと、コールバックが登録されていないことになり、コールバックが意図したとおりに発火しないことに注意しなければならない。そのため、did-finish-loadイベントにコールバックを登録し、レンダラプロセスにおけるJavaScriptの実行が完了するまで待つなどの工夫が必要になる。