javascript
1function animate() { 2 $('#hoge').fadeTo(2000, 1, function() { 3 $('#foo').hide(); 4 $('#bar').fadeTo(1000, 1); 5 }); 6}
上記のように書くと、
"#hoge"のフェードインが完了した後に
"#foo"が非表示になると同時に"#bar"がフェードインします。
しかし、
javascript
1function animate() { 2 $('#hoge').fadeTo(2000, 1, function() { 3 $('#foo').hide(); 4 }); 5 $('#bar').fadeTo(1000, 1); 6}
上記のように書くと、
"#hoge"のフェードインと同時に"#bar"がフェードインします。
何故このようになるのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
JavaScriptはシングルスレッドで動作するので、特殊な機能を使わなければ同時に2つの処理を走らせる事は不可能です。
そして、document.writeでHTMlを無理やり修正できる(非推奨です)存在があるので、
ブラウザはJavaScriptを走らせるとページの動作を一時的にストップさせます。
なのでwhileで無限ループを作って無理やりスリープさせるとブラウザ全体が停止する大惨事に繋がります。
まぁ、スリープしたり待ったりすることが出来ない言語と考えてください。
その代わり、イベントという特定の条件を満たした場合、処理を再開する仕組みを持っています。
代表的なのがjQueryでも多くの場面で使われているsetTimeout、
「○○ミリ秒経過したら引数に渡した関数を実行しておいてね」とお願いするだけで、その場では関数を実行する事なくスルーしてしまいます。
そしてJavaScriptは今実行している処理が全て終了した後、
「あ、そういえばsetTimeoutで登録されたんだったよな…タイムアウトになってる物はあるかな?」と探しに行きます。
タイムアウトになっているモノを見つければ、登録済みの関数を実行するわけですね。
このような仕組みで擬似的にスリープや○○完了を待つという事を実現しているのです。
まぁシングルスレッドで同時に同じ処理は1個しか走りませんが、
JavaScriptは高速で1秒間に何万もこういった処理を次々と捌いてくれますので、
ほぼ並列処理の世界であり「非同期処理」と呼ばれています。
JavaScriptにはアニメーションという機能は存在しません。
そこで、テレビアニメやゲームの画面のようにパラパラ漫画を作る事によって実現させています。
短い時間で何度もDOM要素を掴んでCSSのwidthやleft等の値を書き換えて瞬間移動させる処理を繰り返すわけですね。
TVアニメが秒間15回前後ですが、ゲームは秒間30/60回画面を更新するものが多いです。
ざっくり大体1/60秒のタイミングで動けば滑らかなんじゃないでしょうか。
JavaScript
1var fn = function () { 2 // 経過時間に応じてDOMのプロパティを弄って瞬間移動させる処理 3 setTimeout(fn, 17); // 1/60秒は約16.6ミリ秒です 4}
jQueryは便利なライブラリですが、中で動いているコードはネイティブのJavaScript。
アニメーションという機能は上記のものと同じくsetTimeoutを利用しながら何度も要素を瞬間移動させてるわけです。
setTimeoutを呼ぶという事はその場では何も処理は実行しませんね。
質問文の内容通り、アニメーションの次の処理は質問文のコードを全て舐め終わってから更に17ミリ秒経った後に実行されます。
アニメーション完了時に走ってほしい処理も当然アニメーションが終わった後です。
見分け方は簡単です。
ライブラリや組み込み関数でコールバック関数を求めるものは全てこの仕組みです。
「終わったら、引き続き処理するよ」というやつですね。
何故ならば普通の計算等を行い待ってくれる同期的な処理の場合、
完了後の処理はその次の行に書けば自動的に待ってくれますよね。
つまり、コールバック関数など使う必要はなく、単に複雑で面倒な書き方をしているだけです。
私はsetTimeoutに登録するだけだぞ、終わってから実行してほしい処理があったら教えてくれよ!
…という意図があるからこそ、コールバック関数を引数にくださいと言っているのです。
分かりやすいように簡単なコードを用意しました。
JavaScript
1// コールバック関数を求めるけど同期実行になる例 2var fn = function (cb) { 3 cb(); 4} 5fn(function(){ 6 console.log(1); 7}); 8console.log(2); 9// 1 -> 2 の順に表示される 10 11// 非同期になる専用関数を利用する例 12var fn2 = function (cb) { 13 setTimeout(cb, 0); // 0ミリ秒後実行だとしても一旦処理完了を待つので必ず後になる 14} 15fn2(function(){ 16 console.log(1); 17}); 18console.log(2); 19// 2 -> 1 の順に表示される 20 21// 直接使っても非同期 22setTimeout(function(){ 23 console.log(1); 24}, 0); 25console.log(2); 26// 2 -> 1 の順に表示される
【おまけ】
他にもこういう風に実行を予約はするけど、その場では何もしない機能は沢山あります。
代表例がaddEventListenerという機能です。
これはDOMツリーの描画が終わった瞬間、ユーザーがブラウザでマウスをクリックした時、スクロールした時…などなどのタイミングを指定して、
第二引数として渡したコールバック関数を実行させるという作りです。
その場で実行させようがないので当然非同期です。
先程アニメーションはsetTimeoutで表現すると書きましたが、
最近のブラウザでは約1/60秒に一度のブラウザの描画更新タイミングと同時に処理を挟み込むrequestAnimationFrameが用意されています。
setTimeoutより滑らかにレンダリング出来るので、jQueryでもrequestAnimationFrameが実装されているか否かを判定しながら優先的に扱ってくれるそうです。
まぁsetTimeoutと同じく短い時間待たなければ実行出来ないので当然非同期。
Ajaxを司っているXMLHttpRequestもHTTP通信が終わった後に実行しますのでこの類に含まれますね。
HTTP通信は遅く、同期的に待たせると平気で数秒ブラウザが固まるのでこれも非同期で使うのが基本です。
投稿2018/02/21 11:48
総合スコア21158
0
ベストアンサー
アニメーションが非同期処理だからです。
.fadeTo
などのメソッドを実行すると、アニメーションを開始しただけで戻ってきて、アニメーションの進行を待ちません。なので、次に実行したアニメーションも、ほぼ同じタイミングで進んでいきます。
投稿2018/02/21 06:47
総合スコア145121
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/22 08:42