ブラウザ機能拡張って便利なんですが、世の中であまり使われている気がしません。
こんなに便利なのに、何故使われないんでしょう?
それは、知らないから・・・ではないでしょうか?
もったいないですね。
今回は、Chrome機能拡張の開発を行なっている時に、URLを切り替える場面に置いて、ページ読み込み完了を正確に取得したい場合の対応方法です。
ページ読み込み完了取得時の問題点
通常statusで"complete"を判別すれば、読み込み完了になるはずなのですが、ページがリダイレクト処理をしていると、リダイレクト先数分のcompleteが発生してしまいます。
今回のハマリポイントはここだったのですが、completeを取得しただけでは、ページ読み込みが完了していないというWEBページがあるという事なんですよ。
そもそもログインが必要なページで、セッションが切れている場合などは、ログインページにリダイレクトされてしまったり、リンクをクリックした時に、ビーコンタグだったために、いくつも計測サーバーにリダイレクトというたらい回しをされて、最後に目的のページに行き着くわけですが、人間の感覚では気がつかないぐらいの遷移をしているページもあります。
そんなわけで、最後のページを判別するのに、URLで行うという場合も想定できますが、できればスマートに判定してみたいので、sertTimeoutを使ってスニペットを作ってみました。
ソースコード
var timer;
chrome.tabs.onUpdated.addListener(function(tabId , mode , info){
if(typeof mode.status === "undefined"){return}
/*1000ms以内のリダイレクトであれば下記方式で行える。*/
if(mode.status === "loading"){
// loadingが発生すると既存のsetTimeoutをリセットします。
clearTimeout(timer);
}
else if(mode.status === "complete"){
timer = setTimeout(function(){
loadFlg = false;
/*実行したい処理を記述*/
},1000);
}
});
解説
timer変数
setTiomeoutをtimeというグローバル変数に入れて、"complete"したら1秒後に完了する仕組みを作ります。
その際に1秒以内にリダイレクトして"loading"が発生したらグローバルで実行しているsetTimeoutを破棄して、次のcompleteで新たにtimerをセットします。
これにより、1秒以内のリダイレクトであれば、最後に表示されたページが1秒後にfinish判定することができます。
onUpdatedイベントの変数に注意
function(tabId , mode , info)で値を受け取る際に、infoとmodeの両方にstatusフラグがあり、どちらもloading,completeが挿入されますが、modeの方が使い勝手がいいので、そちらの判定で行ったほうが良いようです。
具体的には、
if(typeof mode.status === "undefined"){return}
この箇所ですが、modeにstatusが入っていない場合は、ページ読み込みのstatusではなく、faviconやら別のモジュール読み込みのイベントのようです。
あまり意味が無いので無視してreturnしてしまいましょう。
重複起動禁止
グローバル変数で行っているので、重複実装はできません。
もし重複起動したい場合は、timerのグローバル変数をtabIDで連想配列にするなどの処理をすると実現できるかもしれませんが、今回は対象外とします。
課題ポイント
今のところどのサイトもうまくできているんですが、1秒以上のリダイレクト処理がかかるサイトがある場合、確実にcompleteを複数処理してしまい、finishが複数になってしまいます。
この場合は、sleep処理などを行うか、1秒の箇所を任意に数値変更して対応してください。
そもそもリダイレクト満載ページってどうなん?
ログインページならある程度分かるし、POSTリクエスト回避の処理も納得できるが、Gmailのページなんかは、4回もリダイレクトしていた。
ほんと意味わかりません。おそらくマーケティングデータ取得処理だと思いますが・・・
0 件のコメント:
コメントを投稿