JavaScript非同步的函數非常多,像是:ajax請求、圖片處理、nodejs的資料庫存取 等..
一定有很多剛入門JS人,被非同步的概念折騰的不要不要
偏偏網路上找的教學,一篇比一篇完整(複雜)
所以這邊我就不結解釋async跟Promise的用法了,直接說明如何解決問題,讓程式碼真真正正的「由上而下執行」
在電腦的瀏覽器按F12開啟「DevTools」就能測試下面的程式碼
用很常見的 setTimeout (延遲執行)來說明
如果非同步的函數下面還有程式碼,那麼程式碼就不會是「由上而下執行」
var a = 0; setTimeout(function () { a = 999; // 1秒過後才會執行這裡 }, 1000); console.log(a); // 印出0 |
這時候只需要一個東東就能解決
//在這個區塊裡面的程式碼會一直等待 await new Promise((resolve, reject) => { resolve(); // 呼叫這個函數後,才會繼續往下執行 }) |
只需要用上面的東東把非同步的程式碼包住,程式碼就非常乖的由上而下執行
var a = 0; await new Promise((resolve, reject) => {//進入等待 setTimeout(function () { a = 999; resolve();//繼續往下執行 }, 1000); }) console.log(a); //印出999 |
把這東西用在迴圈裡面也完全沒問題
for (let i = 1; i <= 10; i++) { await new Promise((resolve, reject) => {//進入等待 setTimeout(function () { resolve();//繼續往下執行 }, 1000); }) console.log(i + '秒過去了'); } console.log('全都結束了'); |
這邊有個點要注意
如果要在函數裡面使用這個語法,則必須在function前面加上「async」
呼叫這個函數的地方要在前面加上「await」
//需要等待非同步的函數,前面要加「async」 async function dd() { var a = 0; await new Promise((resolve, reject) => { setTimeout(function () { a = 999; resolve();//繼續往下執行 }, 3000); }) return a; } //呼叫需要等待的非同步函數,前面要加「await」 var d = await dd(); console.log(d);//印出999 |
(下面的程式碼不能直接執行)
最後用請求多個json來示範
假設有一個函數需要傳入3個json才能執行
要取得這3個json,需要對另外三個網址請求資料
如果用上面教的方法來處理,那麼只要宣告好函數,就能輕鬆愉悅的用4行程式碼來解決
var json_A = await get_json('/get_A.json'); var json_B = await get_json('/get_B.json'); var json_C = await get_json('/get_C.json'); 需要傳入3個json才能執行的函數(json_A, json_B, json_C); /** * */ async function get_json(u) { let json = ''; await new Promise((resolve, reject) => { $.ajax({ url: u, type: "get", success: function (s) { json = s; resolve();//繼續往下執行 }, error: function (xhr, ajaxOptions, thrownError) { resolve();//繼續往下執行 } }); }) return json; } |
如果用傳統的寫法就會像這樣
可讀性0分、完全不可維護
都看到這了,不貼個JS也說不過去