# 進階 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)