# JS非同步/異步處理 ###### tags: `JS` 之前在別篇一定也有提過這個,不過這次實務上遇到了一個算是基本的問題但是卻花了不少時間的狀況,就是某個**API原始設計採callback模式** 比方說像axios,給url、header等arguments後發request,最後會回傳一個promise物件,所以可以用await, 但有些第三方服務,當初設計不是採這種方式,它已經被封裝好,要你帶callback做事 我看到就傻掉惹...因為我不想用這種寫法,想用async await啊~~ > 簡單說,假設我今天要「登入」,我用axios就是給上述那些需要的arguments,但今天我這「登入」是一個第三方已經寫好的API,我使用上是 > ````jsx const handleLogin = () =>{ const handleSuccess = (data) =>{ //do something } const handleFail = (data) =>{ //do something } const handleTimeout = (data) =>{ if (data.response_timeout) { // do something when response timeout } else { // do something when request timeout } } thirdPartyService.login(payload) .onSuccess(handleSuccess) .onFail(handleFail) .onTimeout(handleTimeout) } ```` > 只有一開始call`thirdPartyService.login(payload)`時會return一個物件﹐該物件會有`onSccess onFail`等method,你想要做什麼,請分別對應將callback函式傳進去 但我不喜歡這種寫法,為了最後改成使用async await語法糖,讓code可以用同步的方式寫,繞了一大圈,結果發現答案就在一開始MDN對於promise的範例中: ````jsx const promise1 = new Promise((resolve, reject) => { setTimeout(() => { // 將resolve函式傳入,三秒後拿到值,promise // 的status會切回fulfill,拿回來的值則可以用 // 下面的then處理 resolve('foo'); }, 3000); }); promise1.then((value) => { console.log(value); // expected output: "foo" // 真正能印出值得地方要從then的callback著手 }); console.log(promise1); // expected output: [object Promise] // 會印出這個職是因會同步的code還是先跑了,它只辨認出是一個promist物件 ```` > setTimeout本身就是異步的行為,所以很適合用來模擬實務上打API異步的情境 先把程式改成下面這樣 ````jsx const loginPromise = new Promise(resolve=>{ thirdPartyService.login(payload).onSuccess( function(data) { resolve({status:'success',data}) }).onFail(function(data) { resolve({status:'fail',data}) }).onTimeout(function(data) { resolve({status:'timeout',data}) }) }) loginPromise.then(value=>{ switch(value.status){ case:'success' // do something break case:'fail' // do something break case:'timeout' // do something break } }) console.log(loginPromise) // Promise object ```` 但這樣有個小缺點就是操作上還是得在then裡面做,因此最後改為async await的版本: ````jsx const handleLogin = async () =>{ return new Promise(resolve=>{ thirdPartyService.login(payload) .onSuccess(function(data) { resolve({status:'success',data}) }) .onFail(function(data) { resolve({status:'fail',data}) }) .onTimeout(function(data) { resolve({status:'timeout',data}) }) .onAck(function(data) { resolve({status:'ack',data}) }) }) } const res = await handleLogin() console.log(res) // {status:'OOXX',data:{OOXX}} ```` * 一個注意事項: ````jsx var p = new Promise(resolve=>{ setTimeout(()=>{ resolve('result~~') },5000) }) var fn = async () =>{ const r = await p console.log('result', r) return r } await fn() // 如果沒加await,下面的console.log會立刻印出哦! console.log('sync code') ````