溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

node.js學習筆記之promise

發(fā)布時間:2020-04-06 08:43:11 來源:網絡 閱讀:1308 作者:lixiaoyu1223 欄目:web開發(fā)

這篇文章說說我對promise的理解。

promise在ES6之前就有的寫法,在ES6中寫入了語言標準,于是就有了原生promise對象。

promise對象能更好的改善異步操作的回調地獄,把多層嵌套扁平化,看上去像同步執(zhí)行的代碼,更容易閱讀和理解。由于js語法的靈活多變,也導致了promise的寫法多樣。

promise有三種狀態(tài)來表示當前執(zhí)行的進度,pending,resolve,reject。promise執(zhí)行后,默認是pending狀態(tài),意思是正在執(zhí)行,promise有兩種狀態(tài)變化,并且是不可逆的,第一種就是從pending到resolve,從正在執(zhí)行到執(zhí)行成功,第二種是pending到reject,從執(zhí)行中到執(zhí)行失敗。

promise一旦開始執(zhí)行,就不能停止,直到執(zhí)行結束。

如果不設置回調函數,Promise內部拋出的錯誤,不會反應到外部。

當處于Pending狀態(tài)時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。

下面我就針對promise的常規(guī)用法,鏈式調用,all方法,race方法這四方面來說說我對promise的理解。



先說常規(guī)用法:

let promise = new Promise(function (resolve,reject){
	let res = 1+2+3;
	if(res>1){
		resolve(res);
	}else{
		reject("err");
	}
});
//結果接收方式1
promise.then(function (res){
	console.log(res);
},function (err){
	console.log(err);
});
//結果接收方式2
promise.then(function (res){
	console.log(res);
}).catch(function (err){
	console.log(err);
});
//結果接收方式3
promise.then(function (res){
	console.log(res);
});
promise.catch(function (err){
	console.log(err);
});

常規(guī)用法就是聲明一個promise對象,寫入邏輯,根據邏輯的返回結果確定是執(zhí)行成功還是執(zhí)行失敗,執(zhí)行成功就調用resolve方法,該方法接受一個參數,可以把邏輯返回的結果傳到外面來使用。執(zhí)行失敗可以調用reject方法,該方法也可以傳數據到外部,一般是傳錯誤信息。

在上面的代碼中我寫了三種結果接收方式,先說第一種:

//結果接收方式1
promise.then(function (res){
	console.log(res);
},function (err){
	console.log(err);
});

promise有then方法,可以傳兩個參數,兩個參數都是function,用來接收數據,第一個參數是接收邏輯執(zhí)行成功的返回值,第二個參數接收邏輯執(zhí)行失敗的返回值。當然這種看上去也會有一些嵌套的感覺,我一般是不用這種寫法的。

//結果接收方式2
promise.then(function (res){
	console.log(res);
}).catch(function (err){
	console.log(err);
});

我的個人理解是promise提供了then方法,又提供了catch方法,就是為了分別接收不同的邏輯執(zhí)行結果的,then方法就是為了接收成功返回的結果,那相應的,catch方法就是為了接收失敗返回的結果,node.js中鏈式調用很常見,這種寫法也是一種鏈式調用,我是比較喜歡這種用法的。

//結果接收方式3
promise.then(function (res){
	console.log(res);
});
promise.catch(function (err){
	console.log(err);
});

當然,既然promise提供了then和catch兩個方法接收結果,自然也可以用方法3來接收邏輯返回的結果,有些童鞋喜歡看起來很明朗的代碼風格,那就是這種了,這種只是比第二種方式多了(promise對象.)這么一點代碼。其實看起來是挺工整的。


下面再說說promise的鏈式調用:

假設一種情況:你在A文件里記錄的B文件的名字,在B文件里記錄的C的名字,又在C文件里記錄的D文件的名字,你現在知道A文件的名字,想得到D文件的內容,該怎么來寫呢?我會這樣寫:

new Promise(function(resolve,reject){
	let res1 = 1;//res1邏輯
	if(res1){
		console.log("res1",res1);
		resolve(res1);
	}else{
		reject('new Error1()');
	}
}).then(function (res){
	return new Promise(function (resolve,reject){
		let res2 = 2+res;//res2邏輯
		if(res2){
			console.log("res2",res2);
			resolve(res2);
		}else{
			reject("new Error2");
		}
	});
}).then(function (res){
	return new Promise(function (resolve,reject){
		let res3 = 3 + res;//res3邏輯
		if(res3){
			console.log("res3",res3);
			resolve(res3);
		}else{
			reject('new Error3');
		}
	});		
}).then(function (res){
			console.log("res",res);//res3結果
		}
);

先在res1邏輯中用A文件的名字讀取A文件的內容,得到的結果resolve出去。在then中接收。

然后在res2邏輯中取得A文件內容,解析出B文件名字,再讀取B文件內容,resolve出去。在then中接收,一直到res3結果這里得到D文件的內容,如果是用回調函數的話估計就要嵌套很多層了,而用promise,就能很直觀的看清代碼走勢,是不是很簡單,當然這一段代碼我一直覺得應該有更簡潔的寫法,但無奈本領不到家,只能寫成這樣了,如果有大神看見的話,請賜教。

這一段就是promise的鏈式調用,寫個簡潔的就是

new Promise().then().then().then();


好吧,下面說說promise的all方法:

function test(value){
	let promise = new Promise(function (resolve,reject){
		value = value * 2;
		if(value){
			resolve(value);
		}else{
			reject("err"+value);
		}
	});
	return promise;
}

let promArr = [1,2,3,4,5,6,7,8,9,10].map(function (i){
	return test(i);
});
Promise.all(promArr).then(function (posts){
	console.log(posts);
}).catch(function (err){
	console.log(err); 
});

這里假設我需要執(zhí)行10個異步操作,并把他們的結果放到一個數組里同時傳給一個方法,那all方法就能派上用場了,在這里需要重點說明一下:如果10個promise都是返回成功的話,也就是promise內部邏輯都是調用了resolve(value)方法的話,promise.then才能接收到最終的10個promise的結果組成的數組,就是上面代碼中的posts,假如其中一個promise執(zhí)行失敗,那么,不好意思,你就只能在catch中收到這個失敗的promise返回的錯誤信息了,是的,只能收到執(zhí)行失敗的promise返回的錯誤信息,這就是all方法。大概可以理解成這樣:

let a = true && true && true && true;

當所有的表達式都為true時a才能等于true,有一個表達式為false時,a就不能等于true;


下面再說一下race方法。這個方法有點奇特,舉個例子,一個孕婦懷了四胞胎,那誰是老大呢,當然是先出生的是老大了,而race方法最奇特的地方就在于我只想知道老大是誰,不管后面誰是老二老三,或者說race是一個非常狠心的父親,只想要老大這一個孩子,后面的小孩一個也不要,就算出生了也是扔在醫(yī)院不管不問??创a:

function test(value){
	let promise = new Promise(function (resolve,reject){
		setTimeout(function (){
			resolve(value);
		},Math.random() * 10000);
	});
	return promise;
}

let promArr = [1,2,3,4,5,6,7,8,9,10].map(function (i){
	return test(i);
});
Promise.race(promArr).then(function (post){
	console.log('post',post);
}).catch(function (err){
	console.log('err',err); 
}).finally(function (){
	console.log('finally');
});

這個例子的意思是有10個promise,每個的邏輯都是延時一段時間,時間隨機,誰先執(zhí)行完誰就先返回。

最后的結果是post只能得到一個值,但別的延時還沒執(zhí)行完之前,這段程序不會結束,那也就意味著其他9個promise仍然會執(zhí)行到底,但我們是獲取不到他們9個的結果的,只能得到第一個返回的promise的結果。

恩。就先暫時說這么多吧,promise還有一個done方法和finally方法,done方法是放在then鏈最后,是用來捕獲中間發(fā)生的任何異常的,這個沒有試驗,finally據說是不論then和catch執(zhí)行了哪一個都會執(zhí)行finally方法,但我試驗了卻報錯了,有興趣的同學可以研究一下。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI