1. 程式人生 > 其它 >JavaScript中 Promise 的理解

JavaScript中 Promise 的理解

Promise 是什麼?

PromiseES6 提供的一種非同步程式設計解決方案,解決了傳統非同步處理的回撥金字塔問題; Promise 物件是一個建構函式,用來生成 Promise 例項;
Promise 構成:console.dir(Promise);

可以看出,Promise 這個建構函式自己身上有 resolve(), reject(), all(), race() 這幾種常見的方法,原型上有 catch(), then(), finally() 常用的方法,所以 Promise 的例項可以使用 catch(), then() 等方法;

Promise 的用法

  1. Promise
    建構函式接收一個函式作為引數,這個函式有兩個引數,這兩個引數都是函式,由 js引擎提供;
    // 傳遞一個函式作為例項化引數
    const promise = new Promise(function(resolve, reject) {
    	if (/* 非同步操作成功 */) {
            // 改變狀態為 fulfilled
    		resolve(value);
    	} else {
            // 改變狀態為 rejected
    		reject(error);
    	}
    });
    
  2. resolve 函式的作用是將 Promise 物件的狀態從 "待定"(pending) 改變為 "成功"(fulfilled)
    , 在非同步操作成功的時候呼叫,並將非同步操作的結果作為引數傳遞出去;
    reject 函式的作用是將 Promise 物件的狀態從 "待定"(pending) 改變為 "失敗"(rejected), 在非同步失敗的的時候呼叫,並將非同步操作報的錯誤作為引數傳遞出去;
  3. 可以使用 Promise 生成的例項 promise 呼叫 then() 分別指定 fulfilled狀態rejected狀態 的回撥方法;
    /**
     * promise 例項的then方法,接收兩個引數,這兩個引數都是函式
     * 第一個引數:Promise物件的狀態變為 resolved 狀態時呼叫
     * 第二個引數(可選的):Promise物件的狀態變為 rejected 狀態時呼叫
    */
    promise.then(function(value) {
    	// value 為 Promise 物件例項化時呼叫resolve(...)方法傳入的值
    	// success code
    }, function(error) {
    	// error 為 Promise 物件例項化時呼叫reject(...)方法傳入的錯誤
    	// failure code
    });
    

Promise 鏈式寫法

const promise = new Promise(function(resolve, reject) {
	// 獲取一個10 以內的正整數
	const num = Math.floor(Math.random()*10);
	if (num > 5) {
		resolve("num 大於 5");
	} else {
		reject("num 小於 5")
	}
});

// 第一個 then
promise.then(function(value) {
	// 狀態由 pending 變為 fulfilled 的回撥
	// 這裡 value 的值為 (num 大於 5)
	return "成功了";
}, function(error) {
	// 狀態由 pending 變為 rejected 的回撥
	// 這裡 error 的值為 (num 小於 5)
})
// 第二個 then
.then(function(value) {
	// 這裡 value 的值為 上一個 fulfilled 狀態回撥的返回值(成功了)
	console.log(value);  // 如果 num > 5 列印 成功了
});

例項化一個 Promise,引數為一個函式,函式體實現隨機生成一個10以內的正整數,如果 num > 5Promise 狀態改為 fulfilled 狀態,並向下傳遞了一個 "num 大於 5"的字串,反之,將 Promise 狀態改為 rejected 狀態,向下傳遞了一個 "num 小於 5"的字串;
當第一個 promise 的成功回撥裡返回 "成功了" 時,第二個 promise 的成功回撥的引數就是 "成功了";

由此可以看出,第一個 promise 不管成功回撥還是失敗回撥,他的返回值作為第二個 promise 中的成功時回撥函式的引數值;

鏈式寫法能一直then下去的原因:鏈式呼叫靠的是返回新的 promise,來保證可以一直走成功或失敗;

Promise.resovle

返回一個 Promise 例項,這個例項處於 resolve 狀態
根據傳入的引數不同有不同返回值:

  1. 值(物件, 陣列, 字串等):作為 resolve 傳遞出去的值;
  2. Promise 例項:原封不動返回;
// 返回一個立刻成功的promise
// 別人提供 給你一個方法,需要你傳入一個promise,但你只有一個普通的值,
// 你就可以通過這個方法把這個普通的值(string number object)轉成一個promise物件
Promise.resolve = function(value){
	return new Promise(function(resolve){
		resolve(value);
	});
}

Promise.reject

返回一個 Promise 例項,這個例項處於 reject 狀態。
引數一般就是丟擲的錯誤資訊;

//返回一個立刻失敗的promise
Promise.reject = function(reason){
	return new Promise(function(resolve,reject){
		reject(reason);
	});
}

Promise.catch

Promise.prototype.catch 方法是 .then(null, rejection) 的別名,用於指定發生錯誤時的回撥函式;

//catch原理就是隻傳失敗的回撥
Promise.prototype.catch = function(onRejected){
	this.then(null,onRejected);
}

Promise.all

引數:接受一個數組,陣列內都是Promise例項
返回值:返回一個 Promise 例項,這個 Promise 例項的狀態轉移取決於引數的 Promise 例項的狀態變化。當引數中所有的例項都處於 resolve 狀態時,返回的 Promise 例項會變為 resolve 狀態。如果引數中任意一個例項處於 reject 狀態,返回的 Promise 例項變為 reject 狀態;

Promise.all = function(promises){
	return new Promise(function(resolve,reject){
		let done = gen(promises.length,resolve);
		for(let i=0;i<promises.length;i++){
			promises[i].then(function(data){
				done(i,data);
			},reject);
		}
	});
}

Promise.race

引數:接受一個數組,陣列內都是 Promise 例項
返回值:返回一個 Promise 例項,這個 Promise 例項的狀態轉移取決於引數的 Promise 例項的狀態變化。當引數中任何一個例項處於 resolve 狀態時,返回的 Promise 例項會變為 resolve 狀態。如果引數中任意一個例項處於 reject 狀態,返回的 Promise 例項變為 reject 狀態;

Promise.race = function(promises){
	return new Promise(function(resolve,reject){
		for(let i=0;i<promises.length;i++){
			promises[i].then(resolve,reject);
		}
	});
}

總結

Promise 物件有三種狀態,並且不受外界影響,Promise 的狀態一旦改變就不會再變,並且狀態不可逆,只能從 pending(待定) 改變成 fulfilled(成功)pending(待定) 改變成 rejected(失敗);

  1. pending(待定)
  2. fulfilled(成功)
  3. rejected(失敗)

正是因為這些特點導致 Promise 有三個缺點:

  1. 無法取消 Promise,一旦新建就會立即執行,中途無法取消;
  2. 如果沒有設定回撥函式,Promise 內部丟擲的錯誤,不會反映到外部;
  3. Promise 處於 pending 狀態時,無法得知目前進展到哪一個階段,是剛剛開始還是即將完成;

學習借鑑連結

談談我對Promise的理解