解決js ajax同步請求造成瀏覽器假死的問題,jsajax

來源:互聯網
上載者:User

解決js ajax同步請求造成瀏覽器假死的問題,jsajax

一、問題的起因

今天做一個需求遇到了這麼個情況,就是使用者個人中心有個功能,點擊按鈕,可以重新整理使用者當前的積分,這個肯定需要使用到ajax的同步請求了,當時喀喀喀三下五除二寫玩了,大概代碼如下:

/**  * 非同步目前使用者積分 by zgw 20161216  * @return {[type]} [description] */ function flushIntegralSum() {     //點擊按鈕重新整理前修改按鈕的文案,已經去掉點擊事情,防止多次點擊  $("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="flushbutton">正在重新整理</a>');  $.ajax({   url:'URL',   type:'post',   async:false,   // data:{},   success:function(json){    json = eval('('+json+')');    if(json.url){window.location.href=json.url;return;}    $("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" onclick="flushFreeSum();" id="flushbutton">重新整理積分</a>');    if(json.code!=1){     alert(json.msg);    }else{     $("#free_sum").html(json.free_sum);    }    return;   }  }); }

本以為這麼簡單的功能喀喀喀隨便寫寫就沒事了,在啟動並執行時候出現了問題,當使用者點擊重新整理積分按鈕時,文案沒有修改為"正在重新整理",但是ajax請求發送了,於是我查看網頁代碼,發現js其實把文案和html元素繫結的onclick事件去掉了,在請求成功後有變回原來的了,但是頁面上邊文案沒有改變,當時很奇怪,不知道為什麼html代碼裡邊改變了,頁面卻沒有變點變化

二、瞭解問題原因

問題的根源:當時我進行了排查,最後發現是 "async:false" 的問題,換成非同步就沒有問題了,那為什麼同步請求會產生代碼失效的問題呢?

原因:瀏覽器的渲染(UI)線程和js線程是互斥的,在執行js耗時操作時,頁面渲染會被阻塞掉。當我們執行非同步ajax的時候沒有問題,但當設定為同步請求時,其他的動作(ajax函數後面的代碼,還有渲染線程)都會停止下來。即使我的DOM動作陳述式是在發起請求的前一句,這個同步請求也會“迅速”將UI線程阻塞,不給它執行的時間。這就是代碼失效的原因。

三、解決問題

1.我當時使用了 setTimeout 來解決,把ajax代碼放在sestTimeout中,讓瀏覽器重啟一個線程來操作,這樣就解決問題了,代碼如下:

function flushIntegralSum() {     //點擊按鈕重新整理前修改按鈕的文案,已經去掉點擊事情,防止多次點擊  $("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="flushbutton">正在重新整理</a>');  setTimeout(function(){   $.ajax({    url:'URL',    type:'post',    async:false,    // data:{},    success:function(json){     json = eval('('+json+')');     if(json.url){window.location.href=json.url;return;}     $("#flushbutton").replaceWith('<a style="color:#3fb0ff;font-size:14px;" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" onclick="flushFreeSum();" id="flushbutton">重新整理積分</a>');     if(json.code!=1){      alert(json.msg);     }else{      $("#free_sum").html(json.free_sum);     }     return;    }   });  },0)  }

setTimeout的第二個參數設為0,瀏覽器會在一個已設的最小時間後執行

到這裡問題就解決了,但是你可以試試當你點擊按鈕的時候如果需要彈出一個gif圖片,並且圖片一直在旋轉,提示更新中,你會發現圖片雖然會顯示,但是圖片卻是不動的,那是因為雖然同步請求順延強制了,但是它執行期間還是會把UI線程給阻塞。這個阻塞相當牛逼,連gif圖片都不動了,看起來像一張靜態圖片一樣。結論很明顯,setTimeout治標不治本,相當於把同步請求“稍稍”非同步了一下,接下來還是會進入同步的噩夢,阻塞線程,這種方法只適合發請求之前操作簡單的時間短的情況

2.使用 Deferred 來解決

以上這篇解決js ajax同步請求造成瀏覽器假死的問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援幫客之家。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.