ホームページ > 記事 > ウェブフロントエンド > jQuery 同期 Ajax によって引き起こされる UI スレッド ブロック問題の解決策
この記事では、jQuery 同期 Ajax によって引き起こされる UI スレッドのブロック問題とその解決策を主に紹介します。興味がある方は、ぜひ学習してください。今日は自殺しましたが、同期された Ajax によって引き起こされる UI スレッドのブロック問題に遭遇しました。
その理由は、コードの再利用性を向上させるために、さまざまなパラメーターを受け取り、データを取得することのみを担う getData という関数をカプセル化したためです。データ。取り除かれた基本ロジックは次のとおりです。
function getData1(){ var result; $.ajax({ url : 'p.php', async : false, success: function(data){ result = data; } }); return result; }
$('.btn1').click(function(){ var data = getData1(); alert(data); });
$('.btn1').click(function(){ $('.loadingicon').show(); var data = getData1(); $('.loadingicon').hide(); alert(data); });
<?php sleep(3); echo ('aaaaaa'); ?>
ブラウザのレンダリング (UI) スレッドと js スレッドは相互に排他的であり、時間のかかる js 操作を実行すると、ページのレンダリングがブロックされます。非同期 ajax を実行する場合は問題ありませんが、同期リクエストに設定すると、他のアクション (ajax 関数の背後にあるコードとレンダリング スレッド) が停止します。リクエストが開始される前の文に DOM 操作ステートメントが含まれている場合でも、この同期リクエストは実行時間を与えずに UI スレッドを「すぐに」ブロックします。これがコードが失敗する理由です。
setTimeout はブロックの問題を解決します問題の場所がわかったので、解決策を見つけてみましょう。同期ajaxリクエストがスレッドをブロックしないようにするには、setTimeoutを考え、sestTimeoutにリクエストコードを入れて、ブラウザがスレッドを再起動して動作できるようにすれば問題は解決するのではないでしょうか?それ以来、私のコードは次のようになりました:
$('.btn2').click(function(){ $('.loadingicon').show(); setTimeout(function(){ $.ajax({ url : 'p.php', async : false, success: function(data){ $('.loadingicon').hide(); alert(data); } }); }, 0); });
読み込み中の画像が表示されますが! ! !画像が動かないのはなぜですか? それは明らかにアニメーション GIF です。この時点で、同期リクエストは遅延したものの、実行中に UI スレッドがブロックされるだろうとすぐに思いました。このブロッキングは非常に優れており、gif画像さえも動かず、静止画像のように見えます。
結論は明白です。setTimeout は症状を治療しますが、根本的な原因は治療しません。これは、同期リクエストを「わずかに」非同期にするのと同じであり、その後も同期の悪夢に陥り、スレッドがブロックされます。計画は失敗した。
Deferred を使用する時期ですバージョン 1.5 以降、jQuery には Deferred オブジェクトが導入されました。これは、非常に便利な汎用非同期メカニズムを提供します。詳細については、この記事 http://www.jb51.net/article/54762.htm を参照してください。
そこで、次のように Deferred オブジェクトを使用してコードを書き直しました:
function getData3(){ var defer = $.Deferred(); $.ajax({ url : 'p.php', //async : false, success: function(data){ defer.resolve(data) } }); return defer.promise(); } $('.btn3').click(function(){ $('.loadingicon').show(); $.when(getData3()).done(function(data){ $('.loadingicon').hide(); alert(data); }); });
この時点で、問題は解決されました。遅延オブジェクトは非常に強力で便利なので、活用できます。
私のテスト コードはすべて次のとおりです。興味のある学生はテストに使用できます:
<button class="btn1">async:false</button> <button class="btn2">setTimeout</button> <button class="btn3">deferred</button> <img class="loadingicon" style="position:fixed;left:50%;top:50%;margin-left:-16px;margin-top:-16px;display:none;" src="loading2.gif" alt="正在加载" /> <script> function getData1(){ var result; $.ajax({ url : 'p.php', async : false, success: function(data){ result = data; } }); return result; } $('.btn1').click(function(){ $('.loadingicon').show(); var data = getData1(); $('.loadingicon').hide(); alert(data); }); $('.btn2').click(function(){ $('.loadingicon').show(); setTimeout(function(){ $.ajax({ url : 'p.php', async : false, success: function(data){ $('.loadingicon').hide(); alert(data); } }); }, 0); }); function getData3(){ var defer = $.Deferred(); $.ajax({ url : 'p.php', //async : false, success: function(data){ defer.resolve(data) } }); return defer.promise(); } $('.btn3').click(function(){ $('.loadingicon').show(); $.when(getData3()).done(function(data){ $('.loadingicon').hide(); alert(data); }); });</script>
上記の問題は Chrome と IE9 でテストされており、結論は一貫しています。しかし、Firefox でテストしたところ、同期された ajax は UI スレッドをブロックしませんでした。つまり、この問題はまったく存在しません。他のコードでテストしてみましたが、Firefox では、js スレッドが UI スレッドをブロックすることに疑いの余地はありません。考えられる推測の 1 つは、Firefox が同期 ajax を最適化しているということですが、実際のところはまだわかりません。知っている人がいたらアドバイスをお願いします。
以上がjQuery 同期 Ajax によって引き起こされる UI スレッド ブロック問題の解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。