chrome extension の Unchecked lastError value: Error: Could not establish connection. Receiving end does not exist.の対処法

土日だけ生活リズムがめっちゃ狂う。
どうも、伊藤くんです。

この度chrome extensionを開発していて、以下のようなエラーに遭遇しました。

Unchecked lastError value: Error: Could not establish connection. Receiving end does not exist.

タイミングとしては、background.jsからcontent.jsにchrome.tabs.sendMessageでメッセージを送ろうとした時。

どうやらページのローディングがまだ終わってないからダメよ!って言いたいみたいです。

めんどくさいからtry/catchで握りつぶしちまおうと思ったのですが、そこで問題発生。
こやつtry/catchを無視してくるのです。

try文の中で発生しているはずなのに、それをすり抜けてそこでプログラム全体が止まってしまうのです。

調べてみると、以下のページを発見。
https://stackoverflow.com/questions/28431505/unchecked-runtime-lasterror-when-using-chrome-api

chromeAPIは異世界で動いてるからtry/catchしても意味ないンゴよっていうのと、try/catchではなくそもそもエラーが起きないように実装してくれってばよってことみたいです。多分。

ので、try/catchに頼らずsendMessageの前にページ(タブ)のstatus、つまりローディング中であるかどうかを判定するコードを書き、エラーが起きないよう対処しました。

コードは以下です。

function waitPageLoad(callback) {
// 取得するタブの条件
const queryInfo = {
active: true,
windowId: chrome.windows.WINDOW_ID_CURRENT
};

// タブの情報を取得する
chrome.tabs.query(queryInfo, function(result) {
// 配列の先頭に現在タブの情報が入っている
const currentTab = result.shift();

if (currentTab.status === 'complete') {
// ロードが完了していたら、コールバックを実行
callback(currentTab);
} else {
setTimeout(() => {
// まだロード中だった場合は、ちょっとwaitして再帰的にこの処理を繰り返す
waitPageLoad(callback);
}, 50);
}
});
}

現在タブを取得して、それのstatusフィールドを見ます。ローディングが終わっていたらstatusフィールドが’complete’になっているので、そうなっていたらコールバック関数を実行します。ローディング中だったらstatusフィールドは’loading’とかだったと思います。

ローディング中だったら50ミリ秒待ってもっかい同じ処理をするという、ちょっと危なっかしくてダサい処理をしていますが、その辺は多めに見てください。

この関数を使う側は、以下のような感じです。

waitPageLoad((currentTab) => {
chrome.tabs.sendMessage(currentTab.id, 'content.jsへのめっせーじ', () => {});
});

これで、ページのロードが完了してからメッセージを送ることができますので、あの忌まわしいエラーは起きなくなります。

2時間くらいハマってしまったぜ。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です