Javascript 近幾年來受歡迎的原因,有一大部分是因為 JS 可以處理非同步(異步)的問題,也因為可以非同步,所以處理速度快,且可帶給瀏覽者更好的體驗,所以了解如何控制非同步也成了前端重要的技能之一。
無非同步的程式
1 2 3 4 5 6 7 8
| function add(n1, n2) { return n1 + n2; } function testNoAsync() { let result = add(3, 4); console.log(result); }
|
問題的起源,非同步程式
寫程式如果遇到要處理非同步的程式,就會變得複雜了起來,為什麼會複雜?
預設想要延遲執行,卻出現 undefined 程式會一直往下跑, return 的部分不會回傳會被忽略….。
1 2 3 4 5 6 7 8 9 10 11 12 13
| function delayedAdd0(n1, n2, delayTime) { window.setTimeout(function() { console.log(2); return n1 + n2; }, delayTime); console.log(1); } function test() { let result = delayedAdd0(4, 2, 2000); console.log(result); } test();
|
第一個解決方式 : callback 回呼函式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function delayedAdd1(n1, n2, delayTime, callback) { window.setTimeout(function() { callback(n1 + n2); }, delayTime); }
function test1() { delayedAdd1(4, 2, 2000, function(result) { console.log(result); }); } test1();
|
第二個解決方式 : Promise 物件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function delayedAdd2(n1, n2, delayTime) { let p = new Promise(function(resolve, reject) { window.setTimeout(function() { resolve(n1 + n2); }, delayTime); }); return p; }
function test2() { let promise = delayedAdd2(4, 2, 2000); promise .then(function(result) { console.log(result); }) .catch(function(error) { console.log('Error', error); }); }
|
需求: 需要運行兩次的 promise 然後將結果相乘
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function test2a() { let promise1 = delayedAdd2(4, 2, 2000); let promise2 = delayedAdd2(1, 5, 2000); Promise.all([promise1, promise2]).then(function(results) { let answer = results.reduce(function(total, value) { return total * value; }); console.log(answer); }); } test2a();
|
第三個解決方式 : 使用 Async/Await 簡化 Promise 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
function delayedAdd3(n1, n2, delayTime) { return new Promise(function(resolve, reject) { window.setTimeout(function() { resolve(n1 + n2); }, delayTime); }); }
async function test3() { let result = await delayedAdd2(4, 2, 2000); console.log(result); }
|
需求 需要運行兩次的 promise 然後將結果相乘
1 2 3 4 5 6 7 8
| async function test3a() { let result1 = await delayedAdd2(4, 2, 2000); let result2 = await delayedAdd2(3, 1, 3000); let answer = result1 * result2; console.log(answer); } test3a();
|
參考 1 彭彭的課程
參考 2 code