js
Async
Promises
在製作scrollBlog的js實作時,使用到Async/Await 非同步流程控制,讓畫面捲動往下時,可以捲動畫面往下,設定呈現的時間。
接下來的筆記內容主要參考->彭彭直播
test()
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>非同步流程控制 Callback、Promise、Async/Await</title>
<script>
//
function add(n1, n2) {
return n1 + n2;
}
function test() {
let result = add(3, 4);
console.log(result);
}
</script>
</head>
<body>
<h3>非同步流程控制 Callback、Promise、Async/Await</h3>
<button onclick="test();">Test</button>
</body>
</html>
希望能後延遲兩秒,再得到加法的結果,並印出
setTimeout:延遲一段時間,在執行裡面的函式
<script>
// 問題的起源:非同步的程式
function delayedAdd(n1, n2, delayTime) {
debugger
// 設定排程,延遲一段時間後執行
window.setTimeout(function () {
console.log(2);
return n1 + n2;
}, delayTime);
console.log(1);
}
function test() {
let result = delayedAdd(3, 4, 2000);
console.log(result);
}
</script>
1.回呼函式
callback(n1 + n2)
let result = delayedAdd(3, 4, 2000);
,delayedAdd
回傳值抓不到資料的問題,改為delayedAdd(3, 4, 2000, function (result) { console.log(result);});
<script>
// Callback 回呼函式
function delayedAdd(n1, n2, delayTime, callback) {
// 設定排程,延遲一段時間後執行
window.setTimeout(function () {
// 延遲一段時間之後,計算加法,呼叫 callback 函式
callback(n1 + n2);
}, delayTime);
}
function test() {
delayedAdd(3, 4, 2000, function (result) {
console.log(result);
});
}
</script>
2.Promise 物件
程式運行流程:
test()
->呼叫delayedAdd()
delayedAdd()
,建立一個新的promise物件(承諾延遲2秒鐘作加法),物件建立完成後,執行的工作會交由另一個執行序,不等待其完成promise.then()
,會接收2秒鐘之後,如果工作完成,就呼叫resolve(n1 + n2)
,resolve
會接到function (result)
-> 結果為7<script>
// Promise 物件
function delayedAdd(n1, n2, delayTime) {
// 建立 Promise 物件:new Promise(執行函式)
let p = new Promise(function (resolve, reject) {
window.setTimeout(function () {
resolve(n1 + n2); // 工作完成,呼叫 resolve 函式,並且把結果透過參數傳遞進去
}, delayTime);
});
return p;
}
function test() {
let promise = delayedAdd(3, 4, 2000);
promise.then(function (result) {
console.log(result);
});
}
</script>
return p = new Promise(function (resolve, reject) {
window.setTimeout(function () {
resolve(n1 + n2); // 工作完成,呼叫 resolve 函式,並且把結果透過參數傳遞進去
}, delayTime);
});
}
// Promise 物件
function delayedAdd(n1, n2, delayTime) {
// 建立 Promise 物件:new Promise(執行函式)
return new Promise(function (resolve, reject) {
window.setTimeout(function () {
reject(n1 + n2); // 工作完成,呼叫 resolve 函式,並且把結果透過參數傳遞進去
}, delayTime);
});
}
function test() {
let promise = delayedAdd(3, 4, 2000);
promise.then(function (result) {
console.log(result);
}).catch(function (error) {
console.log("error", error)
})
;
}
async function
<script>
// Async/Await 語法:簡化 Promise 語法
function delayedAdd(n1, n2, delayTime) {
// 建立 Promise 物件:new Promise(執行函式)
return new Promise(function (resolve, reject) {
window.setTimeout(function () {
resolve(n1 + n2); // 工作完成,呼叫 resolve 函式,並且把結果透過參數傳遞進去
}, delayTime);
});
}
async function test() {
// 分別等待多個 Promise 完成後才繼續動作
let result1 = await delayedAdd(3, 4, 2000);
console.log(result1)
// let result2 = await delayedAdd(2, 3, 3000);
// let answer = result1 * result2;
// console.log(answer);
}
</script>
let promise1 = delayedAdd(3, 4, 2000);
延遲2秒, let promise2 = delayedAdd(2, 3, 3000);
3+4; 延遲3秒,2+3Promise.all([promise1, promise2]).then()
:等到all裡面的promise都執行完,再執行.then()
function delayedAdd(n1, n2, delayTime) {
// 建立 Promise 物件:new Promise(執行函式)
return new Promise(function (resolve, reject) {
window.setTimeout(function () {
resolve(n1 + n2); // 工作完成,呼叫 resolve 函式,並且把結果透過參數傳遞進去
}, delayTime);
});
}
function test() {
let promise1 = delayedAdd(3, 4, 2000);
let promise2 = delayedAdd(2, 3, 3000);
// 同時等待多個 Promise 都完成之後,才繼續工作
Promise.all([promise1, promise2]).then(function (results) {
let answer = results.reduce(function (total, value) {
return total * value;
});
console.log(answer);
});
}
<script>
// Async/Await 語法:簡化 Promise 語法
function delayedAdd(n1, n2, delayTime) {
// 建立 Promise 物件:new Promise(執行函式)
return new Promise(function (resolve, reject) {
window.setTimeout(function () {
resolve(n1 + n2); // 工作完成,呼叫 resolve 函式,並且把結果透過參數傳遞進去
}, delayTime);
});
}
async function test() {
// 分別等待多個 Promise 完成後才繼續動作
let result1 = await delayedAdd(3, 4, 2000);
let result2 = await delayedAdd(2, 3, 3000);
let answer = result1 * result2;
console.log(answer);
}
</script>
在 async function 中,使用try catch
來處理
以上個為例:
async function test() {
try {
// 分別等待多個 Promise 完成後才繼續動作
let result1 = await delayedAdd(3, 4, 2000);
let result2 = await delayedAdd(2, 3, 3000);
let answer = result1 * result2;
console.log(answer);
} catch (err) {
console.log(err)
} // TypeError: Failed to fetch
}
參考資料:
loupe
回呼函式 Callbacks、Promises 物件、Async/Await 非同步流程控制 - 彭彭直播
從 JavaScript Promise 到 Async Await