スポンサーリンク

Electronでレンダラープロセスからメインプロセスに処理を渡して、また戻る【async/await】

ニッチな話題プログラミング

レンダラープロセスから、メインプロセスで処理を移した後、レンダラープロセスに処理を戻すには、どうすればよいかハマったのでメモをしておきます。

結果としては、IPC通信とasync, awaitという非同期の関数を利用することで、解決しました。

スポンサーリンク

プロセス間通信と処理の流れ

やりたいことは、
・UIの実行ボタンが押して、
・端末のファイル操作を行い、
・終わってからUIに貯めた入力データをクリアする、
ということです。

UIに関するデータは、レンダラープロセスにあります。

ただ、node.jsの処理が必要になると、メインプロセスに処理を渡す必要があります。

メインプロセスの結果をUI側に表示するには、プロセス間でデータを受け渡す必要があります。

しかし、通常のイベントのメッセージ処理では、送りっぱなしで、相手のプロセスで処理されるのを気にしません。

async / await

そこで、非同期関数(async)にして、結果を待つ(await)、という書き方が必要でした。

[rv] = await expression;

await 式は async function の実行を一時停止し、Promise の解決または拒否を待ちます。解決した後に async function の実行を再開します。

await – JavaScript | MDN

await式を使うには、関数をasyncで宣言しておく必要があります。

具体例

関係する部分のコードを残しておきます。

  • renderer.js
  • preload.js
  • main.js

この後処理が今回の肝です。

レンダラープロセスで処理が始まる

レンダラープロセスで非同期関数を宣言して、await式でAPIを呼びます。

レンダラープロセスは、いったん停止して、非同期関数の結果が返ってくるのを待ちます。

// renderer.js
async function executeCommand() {
	var str = getBaseFolderName(nameDrop.value);
	
	setFolderName(str);
	commandObj.folder_name = str;
	if (commandObj.file_list.length > 0 && commandObj.folder_name != "") {
		//alert("process invoke");
		await window.electron.file_manage_process(commandObj);
		
		//alert("process executed");
	  commandObj.folder_name = "";
		commandObj.file_list.splice(0);
		
		document.getElementById("name-input").value = "";
		document.getElementById("result").innerHTML = "";		
	} 
}

プリロードスクリプトのAPIでプロセス間通信

preload.jsのAPIは、ipcRendererを使ってメッセージを送信します。ここでも、非同期で待ちます。

// preload.js
contextBridge.exposeInMainWorld('electron', {
		path: path,
		file_manage_process: async(data) => await ipcRenderer.invoke('file_manage_process', data)
})

メインプロセスで処理を実行する

メインプロセスは、メッセージ受け取ると、node.jsを利用して処理をして結果を返します。

// main.js
ipcMain.handle('file_manage_process', (event, data) => {
    console.log("process called.")
  var file_list = data.file_list
    var folder_name = data.folder_name
    
      var current_folder = path.dirname(file_list[0]);
      var parent_folder = path.dirname(current_folder);
    var new_folder = path.join(parent_folder, folder_name);

    //console.log(new_folder);
    if (!fs.existsSync(new_folder)) {
        fs.mkdirSync(new_folder);
    }
    file_list.forEach(oldPath => {
      var file_name = path.basename(oldPath)
      var newPath = path.join(new_folder, file_name)
      //console.log(newPath);
      fs.rename(oldPath, newPath, function (err) {
              //callback();
          });
      })
})

レンダラープロセスのawait以降に戻る

メインプロセスでの非同期処理が終わると、レンダラープロセスはawait以降の処理に進みます。

これで、プロセスの後処理ができるようになりました。

QRコードを読み込むと、関連記事を確認できます。
Electronでレンダラープロセスからメインプロセスに処理を渡して、また戻る【async/await】
タイトルとURLをコピーしました