請問當使用AJAX async:false且同時欲顯示loading div,會遇到同步阻塞的問題,如同此頁敘述AJAX同步阻塞,在文未作者有提供使用Defered物件及$.when語法來達成此需求。
但如果我是多個AJAX及statement彼此間又都有順序性,應要怎麼做才不會出現波動拳式的coding style呢?
例如:
$("#loading").show();
data1=ajax().complete(()=>{$("#loading").hide();});
foreach(data in data1){
....
}
data2=ajax(data:data1);
foreach(data in data2){
....
}
類似像這樣使用Defered 就會有兩層callback,而我若後面要再對data2進行操作就又更複雜了。
可以使用promise
等資料回傳後在繼續做下一步
每個步驟寫成funtion
之後then
方法做下一個AJAX動作
function getData1() {
return new Promise((resolve, reject) => {
$.get('/');
})
};
function getData2() {
return new Promise((resolve, reject) => {
$.get('/');
})
};
getData1().then((res)=>{
getData2().then((res2)=>{
})
}).catch((error)=>{ // 錯誤處理
})
另外可以參考mdn寫的promise的async funtion文件
這樣還是會有多層問題,例如我有五個getData,而這五個getData分別會去call不同HOST的WEB API.....(所以無法在後端一次運算完再回傳)
gmlin
那就只能用await方式呼叫...
不過這種5次的ajax是設計不良吧...
這其實是有點像爬蟲,業主希望去抓多個WEB(如氣像局/台電...)的資料來做處理,然後我得先依條件去氣象局抓完資料,跟系統DB資料做完運算再丟進台電的WEB API抓資料回來....
有順序的話,在then裡面呼叫下一次的getData就好。要同時呼叫的話,可以用Promise.all。除非你程式沒寫對,否則很難波動拳才對。或是改用axios?
@fillano 請問你說的在then 裡面呼叫下次的getData,是指下面這樣嗎?
getData1().then((res)=>{
...........
..........
.....
getData2().then((res2)=>{
.........
........
.......
getData3().then((res3)=>{
.....
.....
......
})
})
}).catch((error)=>{ // 錯誤處理
})
還是還有其它種寫法呢?
因為不是同時呼叫,所以無法使用Promise.all
可以使用 async
與 await
語法解決波動拳同時具有順序性
這裡使用簡單範例,多個非同步請求的資料串接
$("#btn").click(async function() {
$(".loading").show();
/* 進行多個非同步資料的處理 */
let response;
response = await ajax("Hello ");
response += await ajax("world ");
response += await ajax("!");
/* 上面非同步資料處理完才會繼續往下走 */
$("#repo")[0].innerHTML = response;
$(".loading").hide();
})
/* 非同步模擬類似 ajax 接收資料 */
function wait(ms) {
return new Promise(r => setTimeout(r, ms));
}
async function ajax(data) {
await wait(500); // 這裡可以設秒數模擬取資料的時間
return data;
}
不清楚這樣是不是你所希望的方法
如果不想多層次 可以考慮用 callback的架構,把呼叫跟ajax返回後執行的callback function全都拆開,如果邏輯差不多,恭喜你可以省掉很多程式碼,因為概念很簡單,我就網路上簡單找範例了,基本上這樣就可以控制在非巢狀