---
# System prepended metadata

title: 進階 JavaScript 語法
tags: [JavaScript]

---

# 進階 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結果:
![](https://i.imgur.com/v1NJ8LB.png)

- 自行製造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)
        
      })
    })

```
![](https://i.imgur.com/DBevk4u.png)

:::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()
 
```




:::

![](https://i.imgur.com/fp6GNKK.png)


## 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)
      })
```
![](https://i.imgur.com/FoHeEID.png)
