# 進階 JavaScript 語法
###### tags: `JavaScript`
## try cash / throw new Error
> try cash 只要一遇到 errow 就會立刻跳到 catch,
> 可以自行製造一個error 讓程式跑到 catch 。
- 語法
```javascript=
try {
alessrt ('abc')
} catch (e) {
console.log(e)
}
```
console.log結果:

- 自行製造error
- 語法 `if(條件) throw new Error('錯誤顯示文字')` , throw 除了拋出錯誤以外極少用到。
範例 01:
```javascript=
const validate = (input) => {
try {
// 可以使用 throw 拋出錯誤,通常會使用 new Error
if(input == '') throw new Error('empty');
if(isNaN(input)) throw new Error('not a number');
if(input < 5) throw new Error('too low');
if(input > 10) throw new Error('too high');
console.log('驗證成功');
}
catch(err) {
console.log = `驗證失敗: ${err.message}`;// 驗證失敗 : too low
}
}
validate(1);
```
範例 02 :
```javascript=
const validata = input =>{
try {
if (!input || input.lenght === 0) throw new Error('沒有輸入內容')
if ( input <=0) throw new Error('數字太小。')
if ( input < 10) throw new Error('數字太小大。')
console.log('驗證成功')
} catch (error) {
console.log(error.message)
}
}
validata(10)
```
## Promise
**<font color="#803EBD">Promise</font>** 就跟單字的意思一樣,就是承諾
當承諾達成時,執行 .then() 內的程式,若有錯誤則執行 **<font color="#803EBD">.catch()</font>** 內的程式
假設媽媽說,如果你這禮拜考試及格,下個禮拜就給你零用錢
現在你不知道到底會不會拿到零用錢,有可能你考試順利及格,也有可能因為沒讀書而考不好
這就是一個 **<font color="#803EBD">Promise</font>** ,且有三種狀態
- **<font color="#803EBD">pending</font>** 還沒發生或等待中,你還不知道考試結果
- **<font color="#803EBD">resolved</font>** 順利通過考試,拿到零用錢
- **<font color="#803EBD">rejected</font>** 沒讀書考不好,沒有零用錢
:::info
有 **.than .catch** 就是 Promise
*Promise是物件(Object),有new的都是物件*
定義
resolved 承諾成功/接受的條件
rejected 承諾失敗/拒絕的條件
使用
.than 承諾成功的時候要執行的事情
.catch 承諾失敗的時候要執行的事情
> - 會使用到Promise的情況:
> 使用的函示會有<font color="red">時間延遲的問題</font>,例如API要資料、轉檔....
> 在轉檔或是拿取資料的時間,程式不會等,會繼續跑。所以要使用Promise。
> Promise 會直到回應(取得 or Error)後,程式才會繼續跑。
:::
範例 1 :
```javascript=
const passed = true
// 宣告一個 new Promise (function()=>{
// 承諾的邏輯
// })
const willGetMoney = new Promise((resolve, reject) => {
if (passed) {
// 接受的條件
resolve('得到零用錢')
} else {
// 拒絕的條件(new Error())
reject(new Error('考試不及格'))
}
})
willGetMoney.then(res => {
//接受的時候要執行
console.log(res)
}).catch(err => {
//拒絕的時候要執行
console.log(err.message)
})
```
範例 2 :
```javascript=
const pass= confirm('你通過考試了嗎')
const willGetMoney = new Promise((resolve,reject)=>{
if(pass){
resolve('恭喜')
}else{
reject(new Error('QQ'))
}
})
willGetMoney.then(result=>{
console.log(result)
}).catch(error=>{
console.log(error)
})
```
:::danger
Promise通常會包成function
Promise 會包成一個 function 去 return Promise
因為function => return Promise 所以後面可以接.than.catch
但如果是用 async ()包起來的裡面要用try catch
:::
範例 1 :
```javascript=
const willGetMoney = passed => {
// return Promise
return new Promise((resolve, reject) => {
if (passed) {
resolve('得到零用錢')
} else {
reject(new Error('考試不及格'))
}
})
}
//呼叫了willGetMoney 這個function
//因為return Promise 所以後面可以接.than.catch
willGetMoney(true).then(res => {
console.log(res)
}).catch(err => {
console.log(err.message)
})
```
範例 2 :
```javascript=
const willGetMoney = (pass) => {
return new Promise((resolve, reject) => {
if (pass) {
resolve('恭喜')
} else {
reject(new Error('QQ'))
}
})
}
willGetMoney(pass).then(result => {
console.log(result)
}).catch(error => {
console.log(error)
})
```
## async await
:::info
規則
1. await 只能接 Promise
2. await 只能放在 function, function前面要加上async。
:::
async()寫法範例 :
```javascript=
async function asyncFunc () {
}
//箭頭函式
const asyncFunc = async () =>{
}
```
範例 :
```javascript=
const wait = (ms) => {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('過了'+ms+'毫秒')
},ms)
})
}
//
//用 async() 包起來 用try catch
const asyncFun = async() => {
try {
//呼叫wait() 帶入value ms =>2000
const result1 = await wait(2000)
//console.log wait1的結果。
console.log(result1)
} catch (error) {
}
}
asyncFun()
//結果 2秒後會出現 過了2000毫秒
```
範例 2 : 當 await 的 promise 有錯誤時,會導向 下面的 catch
```javascript=
const wait = (ms,ok) => {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if(ok) resolve('過了'+ms+'毫秒')
else reject(new Error('錯誤,過了'+ms+'毫秒'))
},ms)
})
}
const asyncFun = async() => {
try {
const result1 = await wait(2000,false)
console.log(result1)
} catch (error) {
console.log(error)
}
}
asyncFun()
//結果 2秒後出現 "錯誤,過了2000毫秒"
```
範例 3 : (兩個await)
```javascript=
const wait = (ms,ok) => {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if(ok) resolve('過了'+ms+'毫秒')
else reject(new Error('錯誤,過了'+ms+'毫秒'))
},ms)
})
}
const asyncFun = async() => {
try {
const result1 = await wait(2000,true)
console.log(result1)
const result2 = await wait(3000,true)
console.log(result2)
} catch (error) {
console.log(error)
}
}
asyncFun()
//結果 兩秒後出現 過了2000毫秒
//再過3秒後 出現 過了3000毫秒
//共執行了 5 秒
```
如果不使用await,code會一層一層包下去,會不容易維護
```javascript=
wait(2000,true).then(result1 => {
console.log(result1)
wait(3000,true).then(result2=>{
console.log(result2)
})
})
```

:::danger
async function 回傳的資料型態是 Promise,所以要用 .then() 接
也可以用 Promise.reject 拋出錯誤,讓 .catch() 接
:::
:::danger
注意
在使用 await 的同時,不要錯過同時執行的機會
執行這段程式碼需要 3000 毫秒
```javascript=
const func1 = async () => {
const wait1 = await wait(1500);
const wait2 = await wait(1500);
return wait1 + wait2;
}
func1()
```
但是執行這段程式碼只需要 1500 毫秒,因為兩個 wait 同時發生
```javascript=
const func2 = async () => {
let wait1 = wait(1500);
let wait2 = wait(1500);
wait1 = await wait1;
wait2 = await wait2;
return wait1 + wait2;
}
func2()
```
:::

## Promise.all(Promise.陣列)
==會等全部都執行完,才會回傳資料,或是遇到error。==
陣列所有都成功時會 .then,回傳結果陣列
只要陣列有一個先 reject,會直接到 .catch 並回傳 reject 的那個錯誤
後面可以接 .then .catch 也可以搭配async 、 try catch
陣列會同時執行。
範例 1 : 都成功的時候會同時回傳結果陣列。
```javascript=
const wait = (ms, ok) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (ok) resolve('過了' + ms + '毫秒')
else reject(new Error('錯誤,過了' + ms + '毫秒'))
}, ms)
})
}
Promise.all([wait(2000, true), wait(5000, true)])
.then(results => {
console.log(results)
})
.catch(error => {
console.log(error)
})
//因為兩者會同時執行,所以總共是等了5秒後出現結果
//會等全部的都執行完(成功)後,出現陣列結果(5秒後一起出現)
```
範例 2 : 有一個錯誤(error)的時候,會直接中斷跳到catch,並回傳錯誤的資訊
```javascript=
const wait = (ms, ok) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (ok) resolve('過了' + ms + '毫秒')
else reject(new Error('錯誤,過了' + ms + '毫秒'))
}, ms)
})
}
//只要陣列有一個先 reject,會直接到 .catch 並回傳 reject 的那個錯誤
Promise.all([wait(2000, false), wait(5000, false)])
.then(results => {
console.log(results)
})
.catch(error => {
console.log(error)
})
```
範例 3 : 搭配await寫法
```javascript=
const asyncFunc = async () => {
try {
const results = await Promise.all([wait(2000, true), wait(5000, true)])
console.log(results)
} catch (error) {
console.log(error)
}
}
asyncFunc()
//結果與範例1 相同。
```
## Promise.all(Promise陣列)
==只回傳陣列內第一個完成的==
誰先完成就回傳誰。
只要陣列有一個先 reject,會直接到 .catch 並回傳 reject 的那個錯誤
```javascript=
Promise.race([wait(2000, false), wait(5000, false)])
.then(result => {
console.log(result)
})
.catch(error => {
console.log(error)
})
```
