1. 程式人生 > >ES6 - Promise物件

ES6 - Promise物件

Promise 物件用於一個非同步操作的最終完成(或失敗)及其結果值的表示。簡單點說,它就是用於處理非同步操作的,非同步處理成功了就執行成功的操作,非同步處理失敗了就捕獲錯誤或者停止後續操作。

Promise物件來說,它也有三種狀態:
1.pending
初始狀態,也稱為未定狀態,就是初始化Promise時,呼叫executor執行器函式後的狀態。
2.fulfilled
完成狀態,意味著非同步操作成功。
3.rejected
失敗狀態,意味著非同步操作失敗。

它只有兩種狀態可以轉化,即:
操作成功resolve()
pending -> fulfilled
操作失敗reject()
pending -> rejected

建立一個Promise例項:

let pro = new Promise( (resolve,reject) => {
	if(成功條件){
		resolve('succees data'); //resolve函式裡面的引數,是當使用鏈式操作函式then時能獲取到
	}else{ // 失敗條件
		reject('fail data');//reject函式裡面的引數,是當使用鏈式操作函式catch時能獲取到
	}
});

例項化後的Promise物件pro可以進行鏈式呼叫,而且這個then()方法可以接收兩個函式作為引數,一個是處理成功後的函式,一個是處理錯誤結果的函式。

//第一種寫法
pro.then((data) => { //處理成功後的操作 }, (err) => { //處理失敗後的操作 });

catch()方法和then()方法一樣,都會返回一個新的Promise物件,它主要用於捕獲非同步操作時出現的異常。因此,我們通常省略then()方法的第二個引數,把錯誤處理控制權轉交給其後面的catch()函式。

let pro1 = new Promise( (resolve,reject) => {
	reject('出錯了'); //人為置為失敗,返回一個rejected的Promise例項
});
pro1.then( (data) => {
//因為上面人為置為失敗了,所以then不執行 console.log("這裡是非同步操作成功後執行的"); }).catch( (err) =>{ console.log("這裡是非同步操作失敗後執行的:" + err); }); //最後輸出了: // 這裡是非同步操作失敗後執行的:出錯了

Promise例項物件為一個函式的用法:

let ajax = (num) => {
	return new Promise ( (resolve,reject) => {
	 	if (num > 5){
	 		resolve("大於5");
	 	}else {
	 		reject("不大於5");
	 	}
	})
}

//Promise物件的鏈式操作
ajax(6).then( (data) => {
	console.log(data);
}).catch( (err) => {
	console.log(err);
});

//最後輸出:
// 大於5

如果有若干個非同步任務,需要先做任務1,如果成功,再做任務2,如果中間任何一個任務失敗,才不繼續進行執行處理函式 。
我們需要序列執行這樣的非同步任務,就可以寫成:(其實就是在then方法中再返回一個Promise例項物件,然後後面就能繼續使用then方法進行序列執行任務了。)

let dataJson = {a:1,b:2}
let ajax = () => {
	return new Promise ( (resolve,reject) => {
	 	resolve(dataJson);
	})
}

//Promise物件的鏈式操作
ajax().then( (data) => {
	console.log(data);
	//返回一個Promise例項,方便後面可以繼續使用鏈式操作then和catch
	return new Promise( (resolve,reject) => {
		resolve(22);
	});
	//等價於
	// return Promise.resolve(22);
}).catch( (err) => {
	console.log(err);
}).then( (data2) => { //因為上面又返回了Promise例項,所以還可以使用鏈式操作
	console.log(data2);
});

//最後輸出:
// {a:1,b:2}
// 22

返回的這個Promise物件的狀態主要是根據Promise例項.then()方法返回的值,大致分為以下幾種情況:
1、如果then()方法中返回了一個引數值,那麼返回的Promise將會變成接收狀態(fulfilled)。
2、如果then()方法中丟擲了一個異常,那麼返回的Promise將會變成拒絕狀態(rejected)。
3、如果then()方法呼叫resolve()方法,那麼返回的Promise將會變成接收狀態。
4、如果then()方法呼叫reject()方法,那麼返回的Promise將會變成拒絕狀態。
5、如果then()方法返回了一個未知狀態(pending)的Promise新例項,那麼返回的新Promise就是未知狀態。
6、如果then()方法沒有明確指定的resolve(data)/reject(data)/return data時,那麼返回的新Promise就是接收狀態,可以一層一層地往下傳遞。

例子如下:

let promise2 = new Promise( (resolve, reject) => {
  // 置為接收狀態
  resolve('success');
});

promise2
  .then((data) => {
    // 上一個then()呼叫了resolve,置為接收狀態fulfilled
    console.log('第一個then'); //第一個then
    console.log(data);  // success
    return '2';
  })
  .then((data) => {
    // 此時這裡的狀態也是fulfilled, 因為上一步返回了一個引數值2
    console.log('第二個then'); //第二個then
    console.log(data);  // 2

    // 返回一個rejected的Promise例項
    return Promise.reject("把狀態置為rejected error");
    
  }, (err) => { //then的第二個函式是捕獲錯誤而執行的
    // error
  })
  .then((data) => {
    /* 這裡不執行,因為上一步呼叫reject()方法,那麼返回的Promise將會變成拒絕狀態 */
    console.log('第三個then');
    console.log(data);
    
  }, (err) => {//then的第二個函式是捕獲錯誤而執行的
    // 此時這裡的狀態是rejected, 因為上一步使用了reject()來返回值
    console.log('出錯:' + err); // 出錯:把狀態置為rejected error
  })
  .then((data) => {
    // 沒有明確指定返回值,預設返回fulfilled (如果後面還有then那麼就會是接收狀態)
    console.log('這裡是fulfilled態'); //這裡是fulfilled態
})
//最後輸出:
// 第一個then
// success
// 第二個then
// 2
// 出錯:把狀態置為rejected error
// 這裡是fulfilled態