1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

backgroundの関数を普通に実行させるための小細工

Last updated at Posted at 2019-05-18

##前書
普通にbackgroundに関数を追加して普通にContentScriptから呼びたい

##background側

  • オブジェクトに関数をまとめる
  • オブジェクト内の関数名を配列にして渡す
  • オブジェクト内の関数を実行する
"use strict"

//エクスポートする関数
const ExportFuncs = {	
	TestFunc : (a, b, c) =>{
		return a + b + c;
	},
	TestFuncAsync : (a, b, c) =>{
		return new Promise((resolve)=>{
			setTimeout(()=>{
				resolve(a * b * c);
			}, 2000);
		});
	},
}

//イベントリスナー
chrome.runtime.onMessage.addListener(function( message, sender, sendResponse ) {
	if( message.to === "background" ){
		//new Promiseはreturn trueを先に返すための小細工
		new Promise(async (resolve)=>{
			if( message.msgType === "getFuncNames" ){
				//ExportFuncs内の関数名を配列にしてレスポンスとして返す
				sendResponse(
					Object.keys(ExportFuncs).filter((key)=>{
						//一応関数でフィルター
						return typeof(ExportFuncs[key])==="function";
					})
				);
				
			}else if( message.msgType === "execFunc" ){
				//ExportFuncs内の関数を実行して結果をレスポンスとして返す
				sendResponse(await ExportFuncs[message.funcName](...(message.args||[])))
			}
			resolve();
		});
		//タイムアウト防止
		return true; 
	}
});

##Content Script側

  • ExportFuncs内の関数名の配列から、実行させるためのメッセージを送る関数をまとめたオブジェクトを作成する
  • ↑から関数を実行する
"use strict";
(async ()=>{
	//初期化処理
	const backgroundFuncs = await (new Promise((resolve)=>{ 
		//関数名の配列を取得
		chrome.runtime.sendMessage({ 
			to:"background",
			msgType:"getFuncNames", 
		},(response)=>{
			//配列をオブジェクトにまとめる
			resolve(response.reduce((funcs, key)=>{
				//ExportFuncs内の関数を実行させるためのメッセージを送る関数
				funcs[key] = (...args)=>{
					//awaitできるように、Promiseでラップする
					return new Promise((resolve)=>{ 
						chrome.runtime.sendMessage({ 
							to:"background",
							msgType:"execFunc", 
							funcName: key, 
							args:args,
						},(response)=>{
							resolve(response);
						});
					});
				};
				return funcs;
			},{}));
		});
	}));



	//呼ぶ処理
	console.log(await backgroundFuncs.TestFunc(2, 3, 5)); // 10
	console.log(await backgroundFuncs.TestFuncAsync(2, 3, 5)); // 30
})();

##課題

  • Content Script側をもっとコンパクトにしたいが、background側で関数作って文字列にして送ってevalで戻すくらいしか思いつかないし、そこまでやってもそんなにコンパクトにならない気がする
  • chromeではtop-levelのawaitができた気がするがうまくいかない。何故だろう

##後書

  • 関数自体の定義と実行に手を加えずにすんだのは満足
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?