我的承諾
前言:
callback 地獄
很簡單,就是要串接的api彼此有關聯性,某隻api的callback是回傳成功,才能進行下一隻api的呼叫。這樣的情況其實是很容易出現,我這邊舉了一個簡單的例子,我串接某支open api,並採用callback的寫法,然後重複呼叫4次,只要當上次呼叫回傳成功時,才能進行下次呼叫,於是地獄產生了。
Promise 的狀態與流程
- 通常我們會使用
resolve
、reject
兩個變數來傳送成功與失敗的訊息。 - 狀態==> pending: 等待中的初始狀態,fulfilled: 正確完成,rejected: 已拒絕,操作失敗
- 會建立 Promise 的事件,等待需要調用的時候呼叫它,呼叫時會有相對應的
then()
及catch()
來接收。return new Promise((resolve, reject)=>{ });
Promise 的使用方法
- 需告一個變數,帶入一個function,裏面有promise()
我們可以使用new Promise
來創建一個新的 Promise。Promise 可以帶入一個函式,而這個函式又會被傳入兩個參數:resolve
&reject
。
成功----->呼叫 resolve() 來回傳 --->接著用then
來接續這個非同步執行完後要做的動作
失敗----->呼叫 reject( ) ----> 用catch
來接住錯誤
當 Promise 被解析成 resolve 或 reject 之後,其值就無法再被改變。const myBookList = new Promise((resolve, reject) => { resolve(someValue); // 完成 reject("failure reason"); // 拒絕 });
//需告一個變數,產生一個function,裏面有promise() let beeRun = (someone)=>{ let ran = parseInt(Math.random()*2); //隨機成功或失敗 console.log("ran"+ran) //parsetInt()是用來把字串轉換成整數的函式 return new Promise((resolve, reject)=>{ if(ran == 1){ resolve(`${someone}成功`); }else{ reject(new Error("zzz")); } }); } //呼叫promise的fn beeRun("tinna").then((fast)=>{ console.log(fast); }).catch((lost)=>{ console.log(lost); });
- fn裏面直接return一個promise
function myBookList(url) { return new Promise((resolve, reject) => { // resolve() or reject() }); };
-
可以使用 Promise.race 傳入多個 promise 事件,這個方法僅會回傳第一個完成的事件。
let runPromise = (someone, timer, success=true)=>{ return new Promise((resolve, reject)=>{ //下判斷 if(success){ setTimeout(function(){ resolve(`${someone}跑${timer/ 1000}秒時間`); },timer); }else{ reject(`${someone}失敗`); } }); } // Race Promise.race([runPromise("小明", 3000), runPromise("火箭", 500)]).then( (data)=>{ console.log(data); }).catch((lost)=>{ console.log(lost); });
-
Promise.all()
會同時執行
以下 Promise,在全部完成後統一回傳陣列,這個陣列的內容也是 promise 中 resolve 的內容。Promise.all([runPromise("小明", 3000), runPromise("火箭", 500)]).then( (data)=>{ console.log(data); }).catch((lost)=>{ console.log(lost); });
Chain 鏈接方法
在一開始有提到波動拳的概念,如果不斷的使用 callback 就會出現超級深的巢狀,那麼此時就可以善用 Promise 的 then()。
then()
所 turn 的資料內容會在下一個 then 接收,用此方法就可以減少 Callback 問題,也可以依序執行不同的 promise 事件。
//帶入參數到promise裡
runPromise("小明", 1500).then((mingdata)=>{
console.log(mingdata);
return runPromise("aunti", 4500);
}).then((antidata)=>{
console.log(antidata);
return runPromise("小傑",500);
}).then((jaydata)=>{
console.log(jaydata);
});
如果我們需要依序串連執行多個 promise
功能的話,可以透過 .then()
來做到。
function funcA(check){
return new Promise((resolve, reject)=>{
window.setTimeout(function(){
console.log('A');
resolve('A');
}, (Math.random() + 1) * 1000);
});
}
function funcB(check){
return new Promise((resolve, rejecte)=>{
window.setTimeout(function(){
console.log('B');
resolve('B');
}, (Math.random() + 1) * 1000);
});
}
function funcC(check){
return new Promise((resolve, reject)=>{
window.setTimeout(function(){
console.log('C');
resolve('C');
}, (Math.random() + 1) * 1000);
});
}
funcA().then(funcB).then(funcC);
就可以做到等 funcA()
被 「resolve」之後再執行 funcB()
,然後 resolve 再執行 funcC()
的順序了。
如果我們不在乎 funcA(), funcB(), funcC()誰先誰後,只關心這三個是否已經完成呢?
那就可以透過 Promise.all( ) 來做到:
// funcA, funcB, funcC 的先後順序不重要
// 直到這三個函式都回覆 resolve 或是「其中一個」 reject 才會繼續後續的行為
Promise.all([funcA(), funcB(), funcC()])
.then(function(){ console.log('上菜'); });
引用:
https://goo.gl/YK1c7L
https://goo.gl/UzTfa9