owned this note
owned this note
Published
Linked with GitHub
# <font class="h2">Async/Await 非同步流程控制</font>
###### tags: `javascript`
<style>
.h2 {
background: linear-gradient(135deg,#fff,#537479) ;
color: #537479;
display:block;
padding: 6px 5px;
border-radius: 4px;
}
.h3 {
background: linear-gradient(180deg,#fff 50%,#c9d5d4) ;
color: #537479;
display:block;
padding: 6px 5px;
border-bottom: 3px solid #537479;
}
.h4 {
color: #537479;
font-weight:bold;
font-size:1.1em;
}
</style>
### <font class="h3">解決非同步的方法</font>
1. 回呼函示(早期)
2. Promise物件(es6)
3. Async/Await(es6)
<br><br><br><br>
### <font class="h3">範例一:</font>
```javascript
function mix(){
console.log(1)
setTimeout(()=>{console.log(2)},0)
console.log(3)
console.log(4)
}
mix() //1342
```
<br><br>
### Promise解法
```javascript
let def = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 0);
})
function mix() {
console.log(1)
def.then((res) => {
console.log(res)
}).then(() => {
console.log(3)
console.log(4)
})
}
mix()
```
<br><br>
### async await解法
```javascript
function second(x) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(x)
}, 0)
})
}
async function mix() {
console.log(1)
const sec = await second(2)
console.log(sec)
console.log(3)
console.log(4)
}
mix()
```
<br><br><br><br>
### <font class="h3">範例二:</font>
```javascript
function add(n1, n2){
return n1+n2;
}
function test(){
let result = add(3,4);
console.log(result);
}
test()//7
```
### 非同步範例:

return基本上失效了,印出結果是undefined
<br>
### <font class="h3">使用Async/Await(簡化Promise語法)</font>
背後的運作邏輯其實跟Promise是一樣的
### <font class="h4">➤Promise寫法</font>
```javascript
function delayedAdd(n1, n2, delayTime){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve(n1+n2);
},delayTime);
});
}
function test(){
let promise= delayedAdd(3,4,2000,);
promise.then(function(result){
console.log(result);//7
});
}
test()
```
### <font class="h4">➤Async/Await寫法</font>

這寫簡潔多(語法糖)
<br>
### <font class="h4">➤使用 try、catch </font>
:::danger
javascript是單線程的程式語言,如果程式碼有一個地方出錯整段程式碼就會停掉,所以可以用try、catch避免這問題
:::
:::spoiler 語法
```javascript
try {
// 預期可能會發生錯誤的程式碼
} catch (e) {
// try 區塊有拋出錯誤時,則執行這裡的程式碼
} finally {
// finally 區塊的程式碼一定會在最後被執行
// 你可以省略 finally 區塊
}
```
:::
<br>
```javascript
function delayedAdd(n1, n2, delayTime){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve(n1+n2);
},delayTime);
});
}
async function test(){
try{
let result= await delayedAdd(3,4,2000);
console.log(result)
}catch(error){
console.error(error)
}
};
test()
```
<br>
### <font class="h3">多個任務做相乘範例:</font>
### Promise寫法
```javascript
function delayedAdd(n1, n2, delayTime){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve(n1+n2);
},delayTime);
});
}
function test(){
let promise1 = delayedAdd(3,4,2000);
let promise2 = delayedAdd(2,3.3000);
Promise.all([promise1,promise2]).then(function(results){
let answer = results.reduce(function(total,value){
return total*value;
})
});
console.log(answer);//35
}
test()
```
### Async/Await寫法
```javascript
function delayedAdd(n1, n2, delayTime){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve(n1+n2);
},delayTime);
});
}
async function test(){
let result1= await delayedAdd(3,4,2000);
let result2= await delayedAdd(2,3,3000);
let answer=result1*result2;
console.log(answer)
};
test();//35
```
:::info
:bulb:Async/Await會比Promise等比較久
:::
<br><br>
### <font class="h4">多個任務範例2:</font>
### Promise
```javascript
function funcA(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('A');
resolve('A');
},(Math.random()+1)*1000)
})
}
function funcB(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('B');
resolve('B');
},(Math.random()+1)*1000)
})
}
function funcC(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('C');
resolve('C');
},(Math.random()+1)*1000)
})
}
funcA().then(funcB).then(funcC)
```
<br>
### async/await
```javascript
function funcA(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve('A');
},(Math.random()+1)*1000)
})
}
function funcB(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve('B');
},(Math.random()+1)*1000)
})
}
function funcC(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve('C');
},(Math.random()+1)*1000)
})
}
async function asyncCall(){
let result;
result = await funcA();
console.log(result);
result = await funcB();
console.log(result);
result = await funcC();
console.log(result)
}
asyncCall()
```
<br>
### async/await還可以搭配Promise.all()
```javascript
function funcA(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve('A');
},(Math.random()+1)*1000)
})
}
function funcB(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve('B');
},(Math.random()+1)*1000)
})
}
function funcC(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve('C');
},(Math.random()+1)*1000)
})
}
async function asyncCall(){
let result = await Promise.all([funcA(),funcB(),funcC()])
result.forEach((i)=>{console.log(i)})
}
asyncCall()
// A B C
```
<br><br><br>
### <font class="h3">Ajax範例</font>
### 一般寫法:
```javascript
const WhereAmI = function (country) {
fetch(`https://restcountries.com/v3.1/name/${country}`)
.then(res => res.json())
.then(data => console.log(data[0]))
}
WhereAmI('Taiwan')
```
<br><br>
### async await寫法:
```javascript
const WhereAmI = async function (country) {
const res = await fetch(`https://restcountries.com/v3.1/name/${country}`)
const data = await res.json()
console.log(data[0])
}
WhereAmI('Taiwan')
```
<br><br><br><br>
### <font class="h3">try、catch與throw範例</font>
throw 語句允許我們創建自定義錯誤。
正確的技術術語是:創建或拋出異常(exception)。
如果把throw 與try 和catch 一起使用,那麼您能夠控製程序流,並生成自定義的錯誤消息。
<br>
```htmlembedded
<input id="demo" type="text">
<button type="button" onclick="myFunction()">測試輸入</button>
<p id="message"></p>
```
```javascript
function myFunction() {
let message, x;
message = document.getElementById("message");
message.innerHTML = "";
x = document.getElementById("demo").value;
try {
if (x == "") throw "值為空";
if (isNaN(x)) throw "不是數值";
x = Number(x);
if (x < 5) throw "太小";
if (x > 10) throw "太大";
}
catch (err) {
message.innerHTML = "錯誤: " + err;
}
}
```

<br><br>
### <font class="h3">加上final範例</font>
finally 語句不論之前的try 和catch 中是否產生異常都會執行該代碼塊。
<br>
```htmlembedded
<input id="demo" type="text">
<button type="button" onclick="myFunction()">測試輸入</button>
<p id="message"></p>
```
```javascript
function myFunction() {
let message, x;
message = document.getElementById("message");
message.innerHTML = "";
x = document.getElementById("demo").value;
try {
if (x == "") throw "值為空";
if (isNaN(x)) throw "不是數值";
x = Number(x);
if (x < 5) throw "太小";
if (x > 10) throw "太大";
}
catch (err) {
message.innerHTML = "錯誤: " + err;
}
finally {
document.getElementById("demo").value = "";
}
}
```

<br><br><br><br>
---
https://wcc723.github.io/javascript/2017/12/30/javascript-async-await/