promise(資料整理)--使用 Promise 處理非同步-(筆記)

  • 530
  • 0
  • ES6
  • 2018-08-27

我的承諾

前言:

callback 地獄

很簡單,就是要串接的api彼此有關聯性,某隻api的callback是回傳成功,才能進行下一隻api的呼叫。這樣的情況其實是很容易出現,我這邊舉了一個簡單的例子,我串接某支open api,並採用callback的寫法,然後重複呼叫4次,只要當上次呼叫回傳成功時,才能進行下次呼叫,於是地獄產生了。

Promise 的狀態與流程

  1. 通常我們會使用 resolvereject 兩個變數來傳送成功與失敗的訊息。
  2. 狀態==>  pending: 等待中的初始狀態,fulfilled: 正確完成,rejected: 已拒絕,操作失敗
  3. 會建立 Promise 的事件,等待需要調用的時候呼叫它,呼叫時會有相對應的then()  catch()來接收。
    return new Promise((resolve, reject)=>{
    
           });

     

Promise 的使用方法

  1. 需告一個變數,帶入一個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);
    });

     

  2. fn裏面直接return一個promise
    function myBookList(url) {
      return new Promise((resolve, reject) => {
        // resolve() or reject()
      });
    };

     

  3. 可以使用 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);
    });

     

  4. 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