Lecturer: 土豆
Date: 2019/12/1
vs.
等餐點
點餐
取餐
客人A
客人B
客人C
客人A
等餐點
點餐
取餐
走人!
客人B
走人!
客人C
走人!
菜好囉!
Request A
waiting
send request
data processing
Done!
Request B
Request C
Done!
Done!
待會都會用這個HTML來測試
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Asyncccccccc</title>
</head>
<body>
<script src="change_this.js"></script> <!-- 改這裡!! -->
</body>
</html>
在那古早的時代...
// callback.js
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
];
function getPost() {
setTimeout(() => {
let output = '';
posts.forEach((post, index) => {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
function createPost(post) {
setTimeout(() => {
posts.push(post);
}, 3000);
}
createPost({title: 'Post Three', body: 'This is post three'});
getPost();
3s
1s
Render!
Create!
3s
1s
Render!
Create!
Callback
Callback Function
當createPost完成後,再呼叫getPost
// callback.js
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
];
function getPost() {
setTimeout(() => {
let output = '';
posts.forEach((post, index) => {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
function createPost(post, callback) {
setTimeout(() => {
posts.push(post);
callback();
}, 3000);
}
createPost({title: 'Post Three', body: 'This is post three'}, getPost);
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
];
function getPost() {
setTimeout(() => {
let output = '';
posts.forEach((post, index) => {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
function createPost(post, callback) {
setTimeout(() => {
posts.push(post);
console.log(posts);
callback();
}, Math.random()*1000);
}
createPost({title: 'Post Three', body: 'This is post three'}, getPost);
createPost({title: 'Post Four', body: 'This is post four'}, getPost);
// callback_hell.js
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
];
function getPost() {
setTimeout(() => {
let output = '';
posts.forEach((post, index) => {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
function createPost(post, callback) {
setTimeout(() => {
posts.push(post);
console.log(posts);
callback();
}, Math.random()*1000);
}
createPost({title: 'Post Three', body: 'This is post three'}, () => {
createPost({title: 'Post Four', body: 'This is post four'}, () => {
getPost();
})
});
// callback_hell.js
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
];
function getPost() {
setTimeout(() => {
let output = '';
posts.forEach((post, index) => {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
function createPost(post, callback) {
setTimeout(() => {
posts.push(post);
console.log(posts);
callback();
}, Math.random()*1000);
}
createPost({title: 'Post Three', body: 'This is post three'}, () => {
createPost({title: 'Post Four', body: 'This is post four'}, () => {
createPost({title: 'Post Five', body: 'This is post five'}, () => {
createPost({title: 'Post Six', body: 'This is post six'}, () => {
createPost({title: 'Post Seven', body: 'This is post seven'}, () => {
createPost({title: 'Post Eight', body: 'This is post eight'}, () => {
createPost({title: 'Post Nine', body: 'This is post nine'}, () => {
createPost({title: 'Post Ten', body: 'This is post ten'}, () => {
getPost();
})
})
})
})
})
})
})
});
by 一年前的我
ES6時代
function promise_func(){
return new Promise((resolve, reject) => {
const error = false;
if (!error) {
resolve('done!');
} else {
reject('Error!');
}
});
}
promise_func().then(value => {console.log(value)});
/*
promise_func()
.then(value => {console.log(value)})
.catch(err => {console.log(err)});
*/
// promise.js
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
];
function getPost() {
setTimeout(() => {
let output = '';
posts.forEach((post, index) => {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
function createPost(post) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (typeof(post) !== "object") {
reject("Wrong data type!");
} else {
posts.push(post);
resolve("done");
}
}, 3000);
});
}
createPost({title: 'Post Three', body: 'This is post three'})
.then(getPost)
.catch(err => {console.log(err)});
// promise_chain.js
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
];
function getPost() {
setTimeout(() => {
let output = '';
posts.forEach((post, index) => {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
function createPost(post) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (typeof(post) !== "object") {
reject("Wrong data type!");
} else {
posts.push(post);
resolve("done");
}
}, Math.random()*1000);
});
}
createPost({title: 'Post Three', body: 'This is post three'})
.then(() => createPost({title: 'Post Four', body: 'This is post four'}))
.then(() => createPost({title: 'Post Five', body: 'This is post five'}))
.then(() => createPost({title: 'Post Six', body: 'This is post six'}))
.then(() => createPost({title: 'Post Seven', body: 'This is post seven'}))
.then(() => createPost({title: 'Post Eight', body: 'This is post eight'}))
.then(() => createPost({title: 'Post Nine', body: 'This is post nine'}))
.then(() => createPost({title: 'Post Ten', body: 'This is post ten'}))
.then(getPost).catch(err => {console.log(err)});
callback hell的promise版本
如果用node.js跑,請先
npm install node-fetch --global
然後在程式碼加上
const fetch = require('node-fetch');
// fecth_something.js
let data = fetch("http://jsonplaceholder.typicode.com/users").then(res =>
res.json()
).then(value =>
console.log(value)
);
fetch是瀏覽器提供的api,所以請在瀏覽器上跑
fetch會幫我們跟伺服器要資料
ES7時代
// async_await_basic.js
// 前面一樣要有一個回傳promise物件的函數
function promise_func(){
return new Promise((resove, reject) => {
const error = true;
if (!error) {
resove("Done!");
} else {
reject("Error!");
}
});
}
// 但是在處理這個promise物件時,可以不用then來處理,改成async/await
(async () => {
let value = await promise_func();
console.log(value);
})();
// errer handler版本
/*
(async () => {
try {
let value = await promise_func();
} catch(e) {
console.log(e);
}
console.log(value);
})();
*/
async加在function前面
await只能在async的function內使用
async內部的await會依序執行,外部則不受影響
處理promise的另一種方式
wait
execute
宣告一個函式之後就馬上執行
// iife_demo.js
(function iife_func(){
console.log("Yo ho!");
})();
// 加上參數
(function hello(name){
console.log(`Hello ${name}`);
})('Sam');
// arrow function version
// 箭頭函數版本,當你硬是要有個function又不想幫它取名時
(() => {
console.log('Yo hoooooo!');
})();
// async_await.js
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
];
function getPost() {
setTimeout(() => {
let output = '';
posts.forEach((post, index) => {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
function createPost(post) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (typeof(post) !== "object") {
reject("Wrong data type!");
} else {
posts.push(post);
resolve("done");
}
}, 3000);
});
}
(async () => {
try {
await createPost({title: 'Post Three', body: 'This is post three'});
} catch(e) {
console.log(e);
}
getPost();
})();
看起來又更簡單了
// async_await_not_hell.js
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
];
function getPost() {
setTimeout(() => {
let output = '';
posts.forEach((post, index) => {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
function createPost(post) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (typeof(post) !== "object") {
reject("Wrong data type!");
} else {
posts.push(post);
resolve("done");
}
}, Math.random()*1000);
});
}
(async () => {
try {
await createPost({title: 'Post Three', body: 'This is post three'});
await createPost({title: 'Post Four', body: 'This is post four'});
await createPost({title: 'Post Five', body: 'This is post five'});
await createPost({title: 'Post Six', body: 'This is post six'});
await createPost({title: 'Post Seven', body: 'This is post seven'});
await createPost({title: 'Post Eight', body: 'This is post eight'});
await createPost({title: 'Post Nine', body: 'This is post nine'});
await createPost({title: 'Post Ten', body: 'This is post ten'});
} catch(e) {
console.log(e);
}
getPost();
})();
看起來一點都不hell了呢
// async_await_fetch_something.js
(async () => {
let res = await fetch("http://jsonplaceholder.typicode.com/users");
res = await res.json();
console.log(res);
})();
// ...
if (event.text.includes("喵喵講話")){
(async () => {
const result = await web.chat.postMessage({
text: '話。',
channel: event.channel,
});
})();
// ...
這邊使用了async / await處理傳送訊息的函式
hint: 一天有兩次預報(0點到6點、6點到18點),任選一個即可
(async () => {
let res = await fetch('https://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire&rid=e6831708-02b4-4ef8-98fa-4b4ce53459d9&limit=14');
let data = await res.json();
data = data.result.results;
let weathers = '';
for (let [i, d] of data.entries()) {
if (i % 2 !== 0){
weathers += `<li>${d.startTime.match(/\d{4}-\d{2}-\d{2}/)}: ${d.parameterName1}</li>`;
}
}
document.body.innerHTML = weathers;
})();