iT邦幫忙

0

AJAX同步阻塞問題

請問當使用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進行操作就又更複雜了。

看更多先前的討論...收起先前的討論...
後端一次做完再丟回來?
gmlin iT邦新手 5 級 ‧ 2021-10-26 10:51:49 檢舉
因為第一個foreach(data in data1)除了會對data1操作,還會與表單物件value交互作用,所以無法一次在後端做完再丟回來
qpalzm iT邦新手 1 級 ‧ 2021-10-26 11:21:13 檢舉
使用promise then呢?
gmlin iT邦新手 5 級 ‧ 2021-10-27 10:49:49 檢舉
這樣還是會有多層問題,例如我有五個getData,而這五個getData分別會去call不同HOST的WEB API.....
Mao iT邦新手 1 級 ‧ 2021-11-12 22:56:55 檢舉
  
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
Homura
iT邦高手 1 級 ‧ 2021-10-26 15:27:44

可以使用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文件

看更多先前的回應...收起先前的回應...
gmlin iT邦新手 5 級 ‧ 2021-10-27 10:51:05 檢舉

這樣還是會有多層問題,例如我有五個getData,而這五個getData分別會去call不同HOST的WEB API.....(所以無法在後端一次運算完再回傳)

Homura iT邦高手 1 級 ‧ 2021-10-27 11:33:24 檢舉

gmlin
那就只能用await方式呼叫...
不過這種5次的ajax是設計不良吧...

gmlin iT邦新手 5 級 ‧ 2021-10-27 13:52:17 檢舉

這其實是有點像爬蟲,業主希望去抓多個WEB(如氣像局/台電...)的資料來做處理,然後我得先依條件去氣象局抓完資料,跟系統DB資料做完運算再丟進台電的WEB API抓資料回來....

fillano iT邦超人 1 級 ‧ 2021-10-27 20:59:23 檢舉

有順序的話,在then裡面呼叫下一次的getData就好。要同時呼叫的話,可以用Promise.all。除非你程式沒寫對,否則很難波動拳才對。或是改用axios?

gmlin iT邦新手 5 級 ‧ 2021-10-28 15:01:24 檢舉

@fillano 請問你說的在then 裡面呼叫下次的getData,是指下面這樣嗎?

getData1().then((res)=>{
    ...........
    ..........
    .....
    getData2().then((res2)=>{
        .........
        ........
        .......
        getData3().then((res3)=>{
            .....
            .....
            ......
        })
    })
}).catch((error)=>{ // 錯誤處理

})

還是還有其它種寫法呢?

因為不是同時呼叫,所以無法使用Promise.all

3
Mao
iT邦新手 1 級 ‧ 2021-10-26 15:39:45

可以使用 asyncawait 語法解決波動拳同時具有順序性
這裡使用簡單範例,多個非同步請求的資料串接

$("#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;
}

Codepen 示範

不清楚這樣是不是你所希望的方法
/images/emoticon/emoticon07.gif

gmlin iT邦新手 5 級 ‧ 2021-10-28 15:02:53 檢舉

本來想說這兩天要來試,結果計畫趕不上老闆一句話,只能週未試完,再來回覆了

1
天黑
iT邦研究生 5 級 ‧ 2021-10-26 15:55:19

如果不想多層次 可以考慮用 callback的架構,把呼叫跟ajax返回後執行的callback function全都拆開,如果邏輯差不多,恭喜你可以省掉很多程式碼,因為概念很簡單,我就網路上簡單找範例了,基本上這樣就可以控制在非巢狀

參考連結

gmlin iT邦新手 5 級 ‧ 2021-10-28 15:03:53 檢舉

第一次看到原來還可以這樣寫,這樣真的可以有很多應用,我再來試試

我要發表回答

立即登入回答