首先說,javascript沒有多線程這樣一個說法,我說的只是類似那種效果。其次,不建議使用這種方式解決問題,多線程應該交給后台去做。
但是,如果非要這樣用,有什么方法呢?
我在工作中就遇到了這樣的問題,由於功能等着急用,整體改進會涉及到前后台,改動會非常大,所以先想了一個臨時性的解決方法。
問題場景是:后台管理系統中有一個表格界面,有一千多條記錄,需要為這一千多條記錄每條記錄生成一堆關聯數據,通過多選行和點擊觸發按鈕執行。要生成的關聯數據比較大,涉及到往幾十張表里插入記錄,因此每條記錄的生成過程比較耗時,大概3秒左右。而問題是,這個界面在批量執行時沒有進度顯示,僅顯示處理中...,在執行一千多條記錄時,等待的時間非常長,用戶往往認為系統死了。為了解決這個問題,我改進了前端處理方法。
思路是:前端模擬一定數量的“線程”提交Http請求,每個請求完成后更新計數器值並顯示進度,如果還有數據需要處理,“線程”再自我遞歸調用,直到數據池里的所有數據處理完畢。
舉例:將100萬元散人民幣分別分給10個人(10個線程)去整理,按1萬元進行打捆,每人一次只能拿1萬元,打捆完畢后再拿1萬元,周而復始,直到100萬元人民幣都整理完。
需要用到的關鍵api:
setInterval(function) -- 這個可以用來防止界面阻塞,每個ajax執行完成后都可以更新界面進度顯示。
(function(){})() -- 匿名函數,用於定義一個函數並立即執行。
arguments -- javascript function的內部變量,是對函數本身及參數的引用。
callee() -- 觸發函數的自我遞歸方法
原理及方法:循環執行一定數量的ajax異步請求方法,每個ajax執行完成后再自我遞歸回調,每次請求完成更新統計變量,直到所有任務執行完畢。
代碼示例:
1 messageBox.show("處理中..."); 2 3 //使用setInterval延遲執行 4 setInterval(function(){ 5 //創建一批10個“線程” 6 for(var i=0;i<10;i++){ 7 8 //使用匿名函數(方便直接自我遞歸調用) 9 (function(){ 10 //如果所有數據已處理完,退出(略) 11 //獲取一批未處理的記錄(略) 12 var funarg = arguments;//得到匿名函數本身引用 13 ajax({ 14 url:'xxx', 15 param:'ids=1,2,3', 16 async:false, 17 callback:function(){ 18 //改變界面進度、改變已處理列表(略) 19 20 //匿名函數自我遞歸調用 21 funarg.callee(); 22 23 } 24 }); 25 })(); 26 } 27 },200);
