Node.js(十二)——NodeJs中的Promise

爬蟲基于回調(diào)和事件的方式去實(shí)現(xiàn),回調(diào)也是被詬病已久的問題尤其是callback這種,無論是閱讀還是調(diào)試都很費(fèi)勁,甚至我們連代碼的堆棧都看不到,這是一種反人類的寫法,Promise來拜托這種痛苦的方式

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供丹東網(wǎng)站建設(shè)、丹東做網(wǎng)站、丹東網(wǎng)站設(shè)計(jì)、丹東網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、丹東企業(yè)網(wǎng)站模板建站服務(wù),十載丹東做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

傳統(tǒng)方式實(shí)現(xiàn)動(dòng)畫效果:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Promise animation</title>
	<style>
		.ball{
			width:40px;
			height:40px;
			border-radius: 20px;/**圓角**/
		}
		.ball1{
			background: red;
		}
		.ball2{
			background: yellow;
		}
		.ball3{
			background: green;
		}
	</style>
	<script src="./node_modules/bluebird/js/browser/bluebird.js"></script>
	
	</head>
	<body onload="init();">
		<div class="ball ball1" ></div>
		<div class="ball ball2" ></div>
		<div class="ball ball3" ></div>
		<script type="text/javascript">
		
			function init(){
				
				//首先拿到這三個(gè)小球
			var ball1 = document.querySelector('.ball1')
			var ball2 = document.querySelector('.ball2')
			var ball3 = document.querySelector('.ball3')
		
		/**
		 * 動(dòng)畫函數(shù)
		 * @param {Object} ball 球
		 * @param {Object} distance 位置,把球移動(dòng)到哪里
		 * @param {Object} cb 回調(diào)的callback
		 */
			function animate(ball,distance,cb){
				alert(ball)
				//設(shè)定一個(gè)延時(shí)
				setTimeout(function(){
					//拿到球現(xiàn)在距離左邊距的位置
					var marginLeft = parseInt(ball.style.marginLeft,10)
					//判斷左邊距移動(dòng)到和我們傳入的distance的時(shí)候
					//重疊,說明動(dòng)畫執(zhí)行完畢
					if(marginLeft===distance){
						//直接調(diào)用回調(diào)函數(shù)
						cb && cb()
					}else{//小球沒有達(dá)到我們預(yù)期的位置
						//球在我們期望位置的左側(cè)
						if(marginLeft<distance){
							marginLeft++
						}else{//在右側(cè)
							marginLeft--
						}
						
						//調(diào)整球的樣式
						ball.style.marginLeft = marginLeft + 'px'
						//不斷重復(fù)去做,直到移動(dòng)到我們所期望的位置
						animate(ball,distance,cb)
					}
				},13)
				//時(shí)間越短,動(dòng)畫越流暢,1秒鐘60幀
			}
			
			//調(diào)用動(dòng)畫_傳統(tǒng)方式來執(zhí)行動(dòng)畫
			animate(ball1,100,function(){//球從左側(cè)向右側(cè)移動(dòng)100像素
				animate(ball2,200,function(){
					animate(ball3,300,function(){
						//移動(dòng)完畢之后繼續(xù)移動(dòng)ball3
						animate(ball3,150,function(){
							animate(ball2,150,function(){
								animate(ball1,150,function(){
									//end
								})
							})
						})
					})
				})
			})
			
			}
		
			
		</script>
	</body>
</html>

運(yùn)行結(jié)果如下:

Node.js(十二)——NodeJs中的Promise

Promise方式如下:

再使用Promise方法之前先導(dǎo)入npm install bluebird模塊,之后再用script標(biāo)簽來引用

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Promise animation</title>
	<style>
		.ball{
			width:40px;
			height:40px;
			border-radius: 20px;/**圓角**/
		}
		.ball1{
			background: red;
		}
		.ball2{
			background: yellow;
		}
		.ball3{
			background: green;
		}
	</style>
	<script src="./node_modules/bluebird/js/browser/bluebird.js"></script>
	
	</head>
	<body>
		<div class="ball ball1" ></div>
		<div class="ball ball2" ></div>
		<div class="ball ball3" ></div>
		<script type="text/javascript">
		
				
				//首先拿到這三個(gè)小球
			var ball1 = document.querySelector('.ball1')
			var ball2 = document.querySelector('.ball2')
			var ball3 = document.querySelector('.ball3')
		
		/**
		 * 動(dòng)畫函數(shù)
		 * @param {Object} ball 球
		 * @param {Object} distance 位置,把球移動(dòng)到哪里
		 * @param {Object} cb 回調(diào)的callback
		 */
			function animate(ball,distance,cb){
				//設(shè)定一個(gè)延時(shí)
				setTimeout(function(){
					//拿到球現(xiàn)在距離左邊距的位置
					var marginLeft = parseInt(ball.style.marginLeft,10)
					//判斷左邊距移動(dòng)到和我們傳入的distance的時(shí)候
					//重疊,說明動(dòng)畫執(zhí)行完畢
					if(marginLeft===distance){
						//直接調(diào)用回調(diào)函數(shù)
						cb && cb()
					}else{//小球沒有達(dá)到我們預(yù)期的位置
						//球在我們期望位置的左側(cè)
						if(marginLeft<distance){
							marginLeft++
						}else{//在右側(cè)
							marginLeft--
						}
						
						//調(diào)整球的樣式
						ball.style.marginLeft = marginLeft + 'px'
						//不斷重復(fù)去做,直到移動(dòng)到我們所期望的位置
						animate(ball,distance,cb)
					}
				},13)
				//時(shí)間越短,動(dòng)畫越流暢,1秒鐘60幀
			}
			
			
			//如何用promise來執(zhí)行動(dòng)畫呢,先安裝一個(gè)庫(kù)npm install bluebird
			//要安裝在該頁(yè)面同層的下面
			function promiseAnimate(ball,distance){
				return new Promise(function(resolve,reject){
					function _animate(){
						//設(shè)定一個(gè)延時(shí)
						setTimeout(function(){
							//拿到球現(xiàn)在距離左邊距的位置
							var marginLeft = parseInt(ball.style.marginLeft,10)
							if(marginLeft===distance){
								//直接調(diào)用回調(diào)函數(shù)
								resolve()
							}else{//小球沒有達(dá)到我們預(yù)期的位置
								//球在我們期望位置的左側(cè)
								if(marginLeft<distance){
									marginLeft++
								}else{//在右側(cè)
									marginLeft--
								}
								
								//調(diào)整球的樣式
								ball.style.marginLeft = marginLeft + 'px'
								//不斷重復(fù)去做,直到移動(dòng)到我們所期望的位置
								_animate()
							}
						},13)
						//時(shí)間越短,動(dòng)畫越流暢,1秒鐘60幀
					}
					
					//啟動(dòng)調(diào)用
					_animate()
				})
			}
			
			
			promiseAnimate(ball1,100)
				.then(function(){
					return promiseAnimate(ball2,200)
				})
				.then(function(){
					return promiseAnimate(ball3,300)
				})
				.then(function(){
					return promiseAnimate(ball3,150)
				})
				.then(function(){
					return promiseAnimate(ball2,150)
				})
				.then(function(){
					return promiseAnimate(ball1,150)
				})
		</script>
	</body>
</html>

運(yùn)行效果同上。

在callback中,如果調(diào)換動(dòng)畫的執(zhí)行順序或者增加幾個(gè)或者減少幾個(gè),需要重新更改代碼;

如果用promise則是一個(gè)線性的控制無論是閱讀還是維護(hù)的體驗(yàn)上都得到了提升,

這僅僅是在瀏覽器中的應(yīng)用,在NodeJs中回調(diào)的場(chǎng)景更多也更殘忍,

尤其是有遠(yuǎn)程API同步和數(shù)據(jù)庫(kù)查詢、文件讀寫操作的時(shí)候,Promise就能解決這些痛點(diǎn)

并且也遠(yuǎn)不止于此

了解Promise需要了解如下知識(shí)

1.ES6的Promise語言標(biāo)準(zhǔn)、Promise/A+規(guī)范

Promise是針對(duì)JavaScript中的異步場(chǎng)景中的解決方案(傳統(tǒng):回調(diào)、事件機(jī)制、訂閱者、等)

Promise是一個(gè)對(duì)象和JavaScript中普通的對(duì)象沒有什么區(qū)別,

同時(shí)它也是一種規(guī)范,異步操作約定了統(tǒng)一的接口,表示一個(gè)異步操作的最終結(jié)果,

以同步的方式來寫代碼,執(zhí)行的操作是異步的,又保證了程序的執(zhí)行順序是同步的,

只有三種狀態(tài):未完成、已完成、失敗

其中中間轉(zhuǎn)換過程只能發(fā)生一次并且是不可逆的;

意思是指:要么從未完成到已完成,要么從未完成到失敗。

那Promise/A+規(guī)范是什么呢?

升級(jí)版,行為標(biāo)準(zhǔn) 擴(kuò)展了原來的規(guī)范,約定俗成的行為,總之是一個(gè)更為標(biāo)準(zhǔn)的

不同之處:

A+規(guī)范通過術(shù)語thenable來區(qū)分promise對(duì)象

A+定義onFulfiled/onRejected必須是作為函數(shù)來調(diào)用,而且調(diào)用過程必須是異步的

A+嚴(yán)格定義了then方法鏈?zhǔn)秸{(diào)用時(shí)onFulfilled/onRejected的調(diào)用順序

then方法定義如下:

promiseObj.then(onFulfilled,onRejected)

onFulfilled = function(value){
	return promiseObj2
}

onRejected = function(err){}

2.如何使用

鏈?zhǔn)秸{(diào)用,例如:

promiseAnimate(ball1,100)
				.then(function(){
					return promiseAnimate(ball2,200)
				})
				.then(function(){
					return promiseAnimate(ball3,300)
				})
				.then(function(){
					return promiseAnimate(ball3,150)
				})
				.then(function(){
					return promiseAnimate(ball2,150)
				})
				.then(function(){
					return promiseAnimate(ball1,150)
				})

3.在什么場(chǎng)景下使用

只要是異步編程的地方都可以使用,業(yè)務(wù)場(chǎng)景簡(jiǎn)單不要為了使用Promise而使用Promise

Promise庫(kù)有很多,例如:

bluebird

Q

then.js

es6-promise

ypromise

async

native-promise-only

等等

文章名稱:Node.js(十二)——NodeJs中的Promise
鏈接URL:http://muchs.cn/article10/pdggdo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標(biāo)簽優(yōu)化域名注冊(cè)、小程序開發(fā)、網(wǎng)站維護(hù)、網(wǎng)站策劃、用戶體驗(yàn)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化