chrome.runtimeのsendMessageとonMessageでハマった
contentとbackgroundの通信でハマった
chrome拡張を開発していている中で content => background => native app => background => contentと通信を行おうとしていました
コードはこんな感じです↓
// content.js document.addEventListener("fire", event => { chrome.runtime.sendMessage( { "msg": event.detail }, response_from_background => { console.log(response_from_background); } ) });
// background.js chrome.runtime.onMessage.addListener((message_from_content, sender, sendToContent) => { // content.jsから受け取ったmessage_from_contentをnative appに送り、response_from_nativeを受け取る chrome.runtime.sendNativeMessage("native-host", message_from_content, response_from_native => { sendToContent(response_from_native) }); });
content.jsでtype = "fire"のカスタムイベントをlistenして、sendMessageでbackground.jsへメッセージを送ります
background.jsではcontent.jsから送られてきたmessage_from_contentをそのままsendNativeMessageメソッドでネイティブアプリへ送ります
native appから返ってきたresponse_from_nativeをsendToContentでcontent.jsへ返します
content.jsでresponse_from_backgroundを受け取りconsoleへ出力します
以上がやりたかったことです
が、
response_from_backgroundがnullになる
何度やってもbackground.jsからの返り値がnullになってしまいました。
consoleでは以下のようなエラーがでていました
Unchecked runtime.lastError: The message port closed before a response was received.
portが閉じちゃってるっぽい?
解決方法
onMessageでtrueを返してあげるだけでした
// background.js chrome.runtime.onMessage.addListener((message_from_content, sender, sendToContent) => { chrome.runtime.sendNativeMessage("native-host", message_from_content, response_from_native => { sendToContent(response_from_native) }); return true // <= これを追加した });
理由はきちんと公式に書いてありました
This function becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called).
先にメッセージの送信元にtrueを返してあげないと非同期でメッセージを送ってくることをchromeがわかってくれないんですね
このtrueは非同期でメッセージ送るからsendResponseが呼ばれるまではport空けといてねーっていうtrueです
たった1行足すだけで解決しました。ちゃんと公式は最後まで読まないとダメだな。。。