オーバーレイのプログレスバーやテキストが書き換わらない。原因と対策
オーバーレイのプログレスバーやテキストが書き換わらない。なんでだよ!ってなりますよね?
本気で javascriptを学んだ人ならいざ知らず、必要に迫られてそこそこ形になればOKって言語じゃん!って思うんですわ。
私はね?www
で、そんな wordpress のプラグインを書いてるときぶち当たったのがPHPの処理時間制限。
サーバーは、いつまでもプログラムを動かしていていいとか言ってません。
サーバーに負荷がかかるので一定時間以上プログラムが動かないように制限をかけています。
でも処理はやりたい。
そんなとき必要になるのが javascriptとの連携。
その連携方法は別の投稿でやるとして、処理状況をモニタリング表示したいじゃないですか。
今、何パーセント処理が終わってますとかね。
で、オーバーレイ(ウィンドウ)を表示させて、そのオーバーレイ(ウィンド)にプログレスバーを表示せると。
簡単ですわね。
ところが、これで書いてもプログラスバーは、最終100%の状態で処理後に表示される。
が、即消える・・・
つまり、前の処理が終わらないと次の処理に着手されないって構造です。
ですが、javascriptは、それらの下後とは異なり非同期型言語なんです。
つまり、書いてある順番なんか関係ない。
やるべき命令を全部並べててできるものから順番に処理する。
前のプロセスでいうなら、「オーバーレイの表示」はあとまわし。
処理ループして、オーバーレイ表示して。オーバーレイを消去。
それも逆かもしれない。
で、よく書かれているのが「Javascritptの引数は関数でもいい」みたいな。
そこのつっこみはおいといて。
順番を限定するために以下のように書いてみる。
関数を処理するためには引数を処理しないといけない。
ほら、うまく・・・いかないんですわ。
それすら非同期処理だったりするwww
「インターバルタイマー」
つまり、一定時間ごとに処理を行う。
最初にインターバルタイマーで「オーバーレイを表示」
次にループを一つ処理してプログレスバーを更新
で、
処理が終わったら次のインターバル割り込みでオーバーレイを消去して完了。
1つの処理が終わった割り込みでオーバーレイの再描画をやってくれるので、割り込みが起こるたびオーバーレイの表示内容が書き換わるという仕組みです。
対策は、1処理ごとに完結させる。そのためにインターバルタイマーを使って時間割込みで1つづつ処理を行うようにする。
参考までに。
以下のモジュールは、この投稿(JavaScript で ウィンド(オーバーレイ)を表示させる簡単方法)から引っ張ってきています。
この書き込みがあなたの一助になれば幸いです。
本気で javascriptを学んだ人ならいざ知らず、必要に迫られてそこそこ形になればOKって言語じゃん!って思うんですわ。
私はね?www
で、そんな wordpress のプラグインを書いてるときぶち当たったのがPHPの処理時間制限。
サーバーは、いつまでもプログラムを動かしていていいとか言ってません。
サーバーに負荷がかかるので一定時間以上プログラムが動かないように制限をかけています。
でも処理はやりたい。
そんなとき必要になるのが javascriptとの連携。
その連携方法は別の投稿でやるとして、処理状況をモニタリング表示したいじゃないですか。
今、何パーセント処理が終わってますとかね。
で、オーバーレイ(ウィンドウ)を表示させて、そのオーバーレイ(ウィンド)にプログレスバーを表示せると。
簡単ですわね。
オーバーレイのプログレスバーで処理の進捗を表示させる
普通に考えるとオーバーレイのプログレスバーで処理の進捗を表示させるならこんな感じ。0001 オーバーレイの表示
0002 処理ループ{
0003 プログレスバーの表示更新
0004 }
0005 オーバーレイの消去
ところが、これで書いてもプログラスバーは、最終100%の状態で処理後に表示される。
が、即消える・・・
オーバーレイのプログレスバーで処理の進捗を表示させたいなら同期型じゃだめ
前述の書き方は通常の言語で「同期型」と呼ばれるものです。つまり、前の処理が終わらないと次の処理に着手されないって構造です。
ですが、javascriptは、それらの下後とは異なり非同期型言語なんです。
つまり、書いてある順番なんか関係ない。
やるべき命令を全部並べててできるものから順番に処理する。
前のプロセスでいうなら、「オーバーレイの表示」はあとまわし。
処理ループして、オーバーレイ表示して。オーバーレイを消去。
それも逆かもしれない。
で、よく書かれているのが「Javascritptの引数は関数でもいい」みたいな。
Javascriptの引数は関数でもいい、いやほとんどの値を返すモジュールを作れる言語は全部そう
Javascriptの引数は関数でもいい、いやほとんどの値を返すモジュールを作れる言語は全部そう。そこのつっこみはおいといて。
順番を限定するために以下のように書いてみる。
- オーバーレイ表示関数 ( funcA )
- 処理ループ関数(プログラスバーの更新含む) ( funcB )
- オーバーレイ消去関数 ( funcC )
0001 オーバーレイ消去関数( 処理ループ関数(プログラスバーの更新含む)( オーバーレイ表示関数() ) ) );
0002 つまり
0003 funcC( funcB( funcA() ) );
関数を処理するためには引数を処理しないといけない。
ほら、うまく・・・いかないんですわ。
それすら非同期処理だったりするwww
オーバーレイのプログレスバーで処理の進捗を表示させる
オーバーレイのプログレスバーで処理の進捗を表示させるには、タイマーを使うんです。「インターバルタイマー」
つまり、一定時間ごとに処理を行う。
最初にインターバルタイマーで「オーバーレイを表示」
次にループを一つ処理してプログレスバーを更新
で、
処理が終わったら次のインターバル割り込みでオーバーレイを消去して完了。
1つの処理が終わった割り込みでオーバーレイの再描画をやってくれるので、割り込みが起こるたびオーバーレイの表示内容が書き換わるという仕組みです。
オーバーレイのプログレスバーやテキストが書き換わらない。原因と対策 まとめ
オーバーレイのプログレスバーやテキストが書き換わらない原因は、描画処理は最後にまわしていい処理とされるから。対策は、1処理ごとに完結させる。そのためにインターバルタイマーを使って時間割込みで1つづつ処理を行うようにする。
参考までに。
以下のモジュールは、この投稿(JavaScript で ウィンド(オーバーレイ)を表示させる簡単方法)から引っ張ってきています。
0001 <div id="outFrame">
0002 <div id="inFrame">
0003 //オーバーレイの中に表示させるもの
0004 <div id="overlay_title"><b>I am a overlay.</b></div>
0005 <div id="closeButton" >
0006 // ↓ javascriptの場合ループしてる最中はボタンが押せないので a タグに変える。
0007 // (cssを駆使してボタンっぽく見せるとよいね)
0008 <a href="#" OnClick="overlay_close();">Close"</a>
0009 </div>
0010 </div>
0011 </div>
0012
0013 <input type="button" value="オーバーレイを開く" id="openButton" OnClick="overlat_open();">
0014
0015 <script>
0016 var intervalID;
0017 var count;
0018 function overlay_open()
0019 {
0020 $('#openButton').fadeOut();
0021 $('#OutFrame').fadeIn();
0022 intervalID = setInterval("overlay_update()", 50); //インターバルタイマーを起動
0023 }
0024 function overlay_close()
0025 {
0026 clearInterval(intervalID); //インターバルタイマーを止める
0027 $('#openButton').fadeIn();
0028 $('#OutFrame').fadeOut();
0029 }
0030 function overlay_update()
0031 {
0032 count++;
0033 var elem = document.getElementById('overlay_title');
0034 elem.innerHTML = count+' 回目 I am a overlay.';
0035
0036 }
0037 </script>
この書き込みがあなたの一助になれば幸いです。