jQuery – 修改在 $.each() 中使用 AJAX 的方式

如果我們使用 $.each() 去做 AJAX,等候遠端回應有符合預期,才跳往下一個序列。這時候使用 $.each() 並不是一個好方式。我們先來看看在還不太了解異步處理的時候會發生的問題。
遠端 service.php
1 2 3 4 5 |
<?php if ($_GET['type'] == "c") echo "error"; else echo "success"; |
只有當拋來的值等於 c 會回傳 error。
1) 不建議的寫法
這個概念是:把蘋果分給4個人,只有 c 說你給錯了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$(['a', 'b', 'c', 'd']).each(function (index, val){ send(val, function (){ console.log('Send Success : ' + val); }, function(){ console.log('Send Error : ' + val); return false; // 異步處理的關係,無濟於事,無法終止迴圈 }) }) function send(val, success, error){ $.get("service.php", { type : val }, function (data){ if (data == "success") { success.call(this, val) } else { error.call(this, val) } }); } |
輸出
1 2 3 4 5 6 |
Send Success : a Send Success : b Send Error : c Send Success : d |
因為 jQuery 的 AJAX 預設是異步概念,所以當發現給錯的時候已經來不及了,並不能中止迴圈。
2) 建議的寫法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
function each(ele, start){ // 終止條件 if (ele[start] === undefined) return false; var val = ele[start]; $.get("service.php", { type : val }, function (data){ if (data == "success") { console.log('Send Success : ' + val); // 重下一個鍵開始算 each(ele, start + 1); } else { console.log('Send Error : ' + val); } }); } // 從陣列 0 開始 each(['a', 'b', 'c', 'd'], 0); |
輸出
1 2 3 4 5 |
Send Success : a Send Success : b Send Error : c |
這個概念是:把蘋果先分給 a 然後 a 說沒問題,分給 b 然後 b 說沒問題;分給 c 然後 c 說你給錯了,所以程式終止迴圈。d 並不會被發到蘋果。 這個寫法如果要漂亮一點可以改成這樣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
function each(ele, key, success){ // 終止條件 if (ele[key] === undefined) return false; var val = ele[key]; $.get("service.php", { type : val }, function (data){ if (data == "success") { //.call 第一個建帶入 ele,那麼在 callback 的時候可以直接使用 this 替代 success.call(ele, key, val, success); } }); } // 從陣列 0 開始 each(['a', 'b', 'c', 'd'], 0, function (key, val, success){ console.log('Send Success : ' + val); // 從下一個鍵開始算。 this 代表陣列 each(this, key + 1, success); }); |
3) 不建議的同步寫法
如果把 AJAX 改成同步處理,確實也可以用 $.each() 做到第2點的方式,但是這會造成瀏覽器阻塞,用戶體驗差。所以強烈不建議這麼使用囉!看一下不建議的寫法怎麼寫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
$(['a', 'b', 'c', 'd']).each(function (index, val){ var result = send(val); if (result === true){ console.log('Send Success : ' + val); } // 終止迴圈 else { return false; } }) function send(val){ var is_success = false; // 這會取得遠端以後,才往下執行 $.ajax({ url: "service.php", type: "get", // async 取消異步。 如果為 true ,那麼下方的 return is_success 永遠為 false async: false, data: { type: val }, success: function (data){ if (data == "success") { // 修改為 true is_success = true; } } }) return is_success; } |