您好,登錄后才能下訂單哦!
爬蟲基于回調和事件的方式去實現,回調也是被詬病已久的問題尤其是callback這種,無論是閱讀還是調試都很費勁,甚至我們連代碼的堆棧都看不到,這是一種反人類的寫法,Promise來拜托這種痛苦的方式
傳統方式實現動畫效果:
<!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(){ //首先拿到這三個小球 var ball1 = document.querySelector('.ball1') var ball2 = document.querySelector('.ball2') var ball3 = document.querySelector('.ball3') /** * 動畫函數 * @param {Object} ball 球 * @param {Object} distance 位置,把球移動到哪里 * @param {Object} cb 回調的callback */ function animate(ball,distance,cb){ alert(ball) //設定一個延時 setTimeout(function(){ //拿到球現在距離左邊距的位置 var marginLeft = parseInt(ball.style.marginLeft,10) //判斷左邊距移動到和我們傳入的distance的時候 //重疊,說明動畫執行完畢 if(marginLeft===distance){ //直接調用回調函數 cb && cb() }else{//小球沒有達到我們預期的位置 //球在我們期望位置的左側 if(marginLeft<distance){ marginLeft++ }else{//在右側 marginLeft-- } //調整球的樣式 ball.style.marginLeft = marginLeft + 'px' //不斷重復去做,直到移動到我們所期望的位置 animate(ball,distance,cb) } },13) //時間越短,動畫越流暢,1秒鐘60幀 } //調用動畫_傳統方式來執行動畫 animate(ball1,100,function(){//球從左側向右側移動100像素 animate(ball2,200,function(){ animate(ball3,300,function(){ //移動完畢之后繼續移動ball3 animate(ball3,150,function(){ animate(ball2,150,function(){ animate(ball1,150,function(){ //end }) }) }) }) }) }) } </script> </body> </html>
運行結果如下:
Promise方式如下:
再使用Promise方法之前先導入npm install bluebird模塊,之后再用script標簽來引用
<!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"> //首先拿到這三個小球 var ball1 = document.querySelector('.ball1') var ball2 = document.querySelector('.ball2') var ball3 = document.querySelector('.ball3') /** * 動畫函數 * @param {Object} ball 球 * @param {Object} distance 位置,把球移動到哪里 * @param {Object} cb 回調的callback */ function animate(ball,distance,cb){ //設定一個延時 setTimeout(function(){ //拿到球現在距離左邊距的位置 var marginLeft = parseInt(ball.style.marginLeft,10) //判斷左邊距移動到和我們傳入的distance的時候 //重疊,說明動畫執行完畢 if(marginLeft===distance){ //直接調用回調函數 cb && cb() }else{//小球沒有達到我們預期的位置 //球在我們期望位置的左側 if(marginLeft<distance){ marginLeft++ }else{//在右側 marginLeft-- } //調整球的樣式 ball.style.marginLeft = marginLeft + 'px' //不斷重復去做,直到移動到我們所期望的位置 animate(ball,distance,cb) } },13) //時間越短,動畫越流暢,1秒鐘60幀 } //如何用promise來執行動畫呢,先安裝一個庫npm install bluebird //要安裝在該頁面同層的下面 function promiseAnimate(ball,distance){ return new Promise(function(resolve,reject){ function _animate(){ //設定一個延時 setTimeout(function(){ //拿到球現在距離左邊距的位置 var marginLeft = parseInt(ball.style.marginLeft,10) if(marginLeft===distance){ //直接調用回調函數 resolve() }else{//小球沒有達到我們預期的位置 //球在我們期望位置的左側 if(marginLeft<distance){ marginLeft++ }else{//在右側 marginLeft-- } //調整球的樣式 ball.style.marginLeft = marginLeft + 'px' //不斷重復去做,直到移動到我們所期望的位置 _animate() } },13) //時間越短,動畫越流暢,1秒鐘60幀 } //啟動調用 _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>
運行效果同上。
在callback中,如果調換動畫的執行順序或者增加幾個或者減少幾個,需要重新更改代碼;
如果用promise則是一個線性的控制無論是閱讀還是維護的體驗上都得到了提升,
這僅僅是在瀏覽器中的應用,在NodeJs中回調的場景更多也更殘忍,
尤其是有遠程API同步和數據庫查詢、文件讀寫操作的時候,Promise就能解決這些痛點
并且也遠不止于此
了解Promise需要了解如下知識
1.ES6的Promise語言標準、Promise/A+規范
Promise是針對JavaScript中的異步場景中的解決方案(傳統:回調、事件機制、訂閱者、等)
Promise是一個對象和JavaScript中普通的對象沒有什么區別,
同時它也是一種規范,異步操作約定了統一的接口,表示一個異步操作的最終結果,
以同步的方式來寫代碼,執行的操作是異步的,又保證了程序的執行順序是同步的,
只有三種狀態:未完成、已完成、失敗
其中中間轉換過程只能發生一次并且是不可逆的;
意思是指:要么從未完成到已完成,要么從未完成到失敗。
那Promise/A+規范是什么呢?
升級版,行為標準 擴展了原來的規范,約定俗成的行為,總之是一個更為標準的
不同之處:
A+規范通過術語thenable來區分promise對象
A+定義onFulfiled/onRejected必須是作為函數來調用,而且調用過程必須是異步的
A+嚴格定義了then方法鏈式調用時onFulfilled/onRejected的調用順序
then方法定義如下:
promiseObj.then(onFulfilled,onRejected) onFulfilled = function(value){ return promiseObj2 } onRejected = function(err){}
2.如何使用
鏈式調用,例如:
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.在什么場景下使用
只要是異步編程的地方都可以使用,業務場景簡單不要為了使用Promise而使用Promise
Promise庫有很多,例如:
bluebird
Q
then.js
es6-promise
ypromise
async
native-promise-only
等等
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。