[JS] Promise & Callback
callback
解決問題:非同步 asynchronous
缺點:readability, callback hell
解決辦法:Promise
Promise
new Promise( /* executor */ function(resolve, reject) { ... } );
Promise.all
Promise.race
- Promise.all 多個 Promise 行為同時執行,全部完成後統一回傳。
- Promise.race 多個 Promise 同時執行,但僅回傳第一個完成的。
- 當執行到 promise 中的 resolve or reject 後,後面的語法就不會再執行了。
let promise = new Promise(function (resolve, reject) {
resolve(1); //執行成功,下面的語法不會繼續執行。
setTimeout(() => resolve(2), 1000);
});
promise.then(alert); // 1
Promise.resolve vs new Promise
Promise.resolve will create a promise which is already resolved, whereas new Promise(resolve) creates a promise which is neither resolved nor rejected.
Promise.resolve(value) => 接受一個值在resolve裡面。 new Promise() => 建立一個 Promise 然後可以在裡面執行 action,最後在 resolve result。
then, catch, finally 語法
// then, catch
let promise = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// reject runs the second function in .then
promise.then(
(result) => alert(result), // doesn't run
(error) => alert(error) // shows "Error: Whoops!" after 1 second
);
finally: 用於處理額外的狀況
//finally
new Promise((resolve, reject) => {
/* do something that takes time, and then call resolve or maybe reject */
})
// runs when the promise is settled, doesn't matter successfully or not
.finally(() => stop loading indicator)
// so the loading indicator is always stopped before we go on
.then(result => show result, err => show error)
- finally 沒有 arguments。
- finally 會 ignore return 繼續往下一階走。
Async/await
:更直觀的方式來處理 Promise
async function wait() {
await new Promise((resolve) => setTimeout(resolve, 1000));
return 10;
}
function f() {
// shows 10 after 1 second
wait().then((result) => alert(result));
}
f();
Fetch
:用 Fetch 來處理 call api 需求
let response = await fetch("/article/fetch/post/user", {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(user),
});
實踐 Promise.all
function promiseAll(values) {
if (!Array.isArray(values)) return;
return new Promise((resolve, reject) => {
let results = [];
let completed = 0;
values.forEach((value, index) => {
Promise.resolve(value)
.then((result) => {
results[index] = result;
completed += 1;
if (completed == values.length) {
resolve(results);
}
})
.catch((err) => reject(err));
});
});
}
實踐 Promise.race
const PromiseRace = (iterable) => {
return new Promise((resolve, reject) => {
for (const item of iterable) {
Promise.resolve(item).then(resolve).catch(reject);
}
});
};
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://javascript.info/async-await https://javascript.info/fetch https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/140
ajax, xml
https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/ajax_fetch.html