91在线一级黄片|91视频在线观看18|成人夜间呦呦网站|91资源欧美日韩超碰|久久最新免费精品视频一区二区三区|国产探花视频在线观看|黄片真人免费三级片毛片|国产人无码视频在线|精品成人影视无码三区|久久视频爱久久免费精品

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
如何使用Await減少回調(diào)嵌套

在開發(fā)的時(shí)候,有時(shí)候需要發(fā)很多請(qǐng)求,然后經(jīng)常會(huì)面臨嵌套回調(diào)的問(wèn)題,即在一個(gè)回調(diào)里面又嵌了一個(gè)回調(diào),導(dǎo)致代碼層層縮進(jìn)得很厲害,如下代碼所示:

創(chuàng)新互聯(lián)建站2013年至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元那曲做網(wǎng)站,已為上家服務(wù),為那曲各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575

 
 
 
 
  1. ajax({ 
  2.     url: "/list", 
  3.     type: "GET", 
  4.     success: function(data) { 
  5.        appendToDOM(data); 
  6.         ajax({ 
  7.             url: "/update", 
  8.             type: "POST", 
  9.             success: function(data) { 
  10.                 util.toast("Success!"); 
  11.             }) 
  12.         }); 
  13.     } 
  14. }); 

這樣的代碼看起來(lái)有點(diǎn)吃力,這種異步回調(diào)通??梢杂肞romise優(yōu)化一下,可以把上面代碼改成:

 
 
 
 
  1. new Promise(resolve => { 
  2.     ajax({ 
  3.         url: "/list", 
  4.         type: "GET", 
  5.         success: data => resolve(data); 
  6.     }) 
  7. }).then(data => { 
  8.    appendToDOM(data); 
  9.     ajax({ 
  10.         url: "/update", 
  11.         type: "POST", 
  12.         success: function(data) { 
  13.             util.toast("Successfully!"); 
  14.         })   
  15.     });  
  16. }); 

Promise提供了一個(gè)resolve,方便通知什么時(shí)候異步結(jié)束了,不過(guò)本質(zhì)還是一樣的,還是使用回調(diào),只是這個(gè)回調(diào)放在了then里面。

當(dāng)需要獲取多次異步數(shù)據(jù)的時(shí)候,可以使用Promise.all解決:

 
 
 
 
  1. let orderPromise = new Promise(resolve => { 
  2.     ajax("/order", "GET", data => resolve(data)); 
  3. }); 
  4. let userPromise = new Promise(resolve => { 
  5.     ajax("/user", "GET", data => resolve(data)); 
  6. }); 
  7.   
  8. Promise.all([orderPromise, userPromise]).then(values => { 
  9.     let order = values[0], 
  10.          user = values[1]; 
  11. }); 

但是這里也是使用了回調(diào),有沒(méi)有比較優(yōu)雅的解決方式呢?

ES7的await/async可以讓異步回調(diào)的寫法跟寫同步代碼一樣。***個(gè)嵌套回調(diào)的例子可以用await改成下面的代碼:

 
 
 
 
  1. // 使用await獲取異步數(shù)據(jù) 
  2. let leadList = await new Promise(resolve => { 
  3.     ajax({ 
  4.         url: "/list", 
  5.         type: "GET", 
  6.         success: data => resolve(data); 
  7.     }); 
  8. }); 
  9.   
  10. // await讓代碼很自然地像瀑布流一樣寫下來(lái)  
  11. appendToDom(leadList); 
  12. ajax({ 
  13.     url: "/update", 
  14.     type: "POST", 
  15.     success: () => util.toast("Successfully"); 
  16. }); 

Await讓代碼可以像瀑布流一樣很自然地寫下來(lái)。

第二個(gè)例子:獲取多次異步數(shù)據(jù),可以改成這樣:

 
 
 
 
  1. let order = await new Promise( 
  2.            resolve => ajax("/order", data => resovle(data))), 
  3.   
  4.     user = await new Promise( 
  5.            resolve => ajax("/user", data => resolve(data))); 
  6.   
  7. // do sth. with order/user 

這種寫法就好像從本地獲取數(shù)據(jù)一樣,就不用套回調(diào)函數(shù)了。

Await除了用在發(fā)請(qǐng)求之外,還適用于其它異步場(chǎng)景,例如我在創(chuàng)建訂單前先彈一個(gè)小框詢問(wèn)用戶是要?jiǎng)?chuàng)建哪種類型的訂單,然后再?gòu)椌唧w的設(shè)置訂單的框,所以按正常思路這里需要傳遞一個(gè)按鈕回調(diào)的點(diǎn)擊函數(shù),如下圖所示:

但其實(shí)可以使用await解決,如下代碼所示:

 
 
 
 
  1. let quoteHandler = require("./quote"); 
  2. // 彈出框詢問(wèn)用戶并得到用戶的選擇 
  3. let createType = await quoteHandler.confirmCreate(); 

quote里面返回一個(gè)Promise,監(jiān)聽點(diǎn)擊事件,并傳遞createType:

 
 
 
 
  1. let quoteHandler = { 
  2.     confirmCreate: function(){ 
  3.         dialog.showDialog({ 
  4.             contentTpl: tpl, 
  5.             className: "confirm-create-quote" 
  6.         }); 
  7.         let $quoteDialog = $(".confirm-create-quote form")[0]; 
  8.         return new Promise(resolve => { 
  9.             $(form.submit).on("click", function(event){ 
  10.                 resolve(form.createType.value); 
  11.             }); 
  12.         }); 
  13.     } 
  14.   

這樣外部調(diào)用者就可以使用await,而不用傳遞一個(gè)點(diǎn)擊事件的回調(diào)函數(shù)了。

但是需要注意的是await的一次性執(zhí)行特點(diǎn)。相對(duì)于回調(diào)函數(shù)來(lái)說(shuō),await的執(zhí)行是一次性的,例如監(jiān)聽點(diǎn)擊事件,然后使用await,那么點(diǎn)擊事件只會(huì)執(zhí)行一次,因?yàn)榇a從上往下執(zhí)行完了,所以當(dāng)希望點(diǎn)擊之后出錯(cuò)了還能繼續(xù)修改和提交就不能使用await,另外使用await獲取異步數(shù)據(jù),如果出錯(cuò)了,那么成功的resolve就不會(huì)執(zhí)行,后續(xù)的代碼也不會(huì)執(zhí)行,所以請(qǐng)求出錯(cuò)的時(shí)候基本邏輯不會(huì)有問(wèn)題。

要在babel里面使用await,需要:

(1)安裝一個(gè)Node包

 
 
 
 
  1. npm install –save-dev babel-plugin-transform-async-to-generator 

(2)在工程的根目錄添加一個(gè).babelrc文件,內(nèi)容為:

 
 
 
 
  1.   "plugins": ["transform-async-to-generator"] 

(3)使用的時(shí)候先引入一個(gè)模塊

 
 
 
 
  1. require("babel-polyfill"); 

然后就可以愉快地使用ES7的await了。

使用await的函數(shù)前面需要加上async關(guān)鍵字,如下代碼:

 
 
 
 
  1. async showOrderDialog() { 
  2.      // 獲取創(chuàng)建類型 
  3.      let createType = await quoteHandler.confirmCreate(); 
  4.   
  5.      // 獲取老訂單數(shù)據(jù)  
  6.      let orderInfo = await orderHandler.getOrderData(); 

我們?cè)倥e一個(gè)例子:使用await實(shí)現(xiàn)JS版的sleep函數(shù),因?yàn)樵菦](méi)有提供線程休眠函數(shù)的,如下代碼所示:

 
 
 
 
  1. function sleep (time) { 
  2.     return new Promise(resolve =>  
  3.                           setTimeout(() => resolve(), time)); 
  4.   
  5. async function start () { 
  6.     await sleep(1000); 
  7.   
  8. start(); 

babel的await實(shí)現(xiàn)是轉(zhuǎn)成了ES6的generator,如下關(guān)鍵代碼:

 
 
 
 
  1. while (1) { 
  2.     switch (_context.prev = _context.next) { 
  3.         case 0: 
  4.             _context.next = 2; 
  5.             // sleep返回一個(gè)Promise對(duì)象 
  6.             return sleep(1000); 
  7.   
  8.         case 2: 
  9.         case "end":      
  10.             return _context.stop(); 
  11.     } 

而babel的generator也是要用ES5實(shí)現(xiàn)的,什么是generator呢?如下圖所示:

生成器用function*定義,每次執(zhí)行生成器的next函數(shù)的時(shí)候會(huì)返回當(dāng)前生成器里用yield返回的值,然后生成器的迭代器往后走一步,直到所有yield完了。

有興趣的可以繼續(xù)研究babel是如何把ES7轉(zhuǎn)成ES5的,據(jù)說(shuō)原生的實(shí)現(xiàn)還是直接基于Promise.

使用await還有一個(gè)好處,可以直接try-catch捕獲異步過(guò)程拋出的異常,因?yàn)槲覀兪遣荒苤苯硬东@異步回調(diào)里面的異常的,如下代碼:

 
 
 
 
  1. let quoteHandler = { 
  2.     confirmCreate: function(){ 
  3.         $(form.submit).on("click", function(event){ 
  4.             // 這里會(huì)拋undefined異常:訪問(wèn)了undefined的value屬性 
  5.             callback(form.notFoundInput.value); 
  6.         }); 
  7.     } 
  8.   
  9. try { 
  10.     // 這里無(wú)法捕獲到異常 
  11.     quoteHandler.confirmCreate(); 
  12. } catch (e) { 
  13.   

上面的try-catch是沒(méi)有辦法捕獲到異常的,因?yàn)閠ry里的代碼已經(jīng)執(zhí)行完了,在它執(zhí)行的過(guò)程中并沒(méi)有異常,因此無(wú)法在這里捕獲,如果使用Promise的話一般是使用Promise鏈的catch:

 
 
 
 
  1. let quoteHandler = { 
  2.     confirmCreate: function(){ 
  3.         return new Promise(resolve => { 
  4.             $(form.submit).on("click", function(event){ 
  5.                 // 這里會(huì)拋undefined異常:訪問(wèn)了undefined的value屬性 
  6.                 resolve(form.notFoundInput.value); 
  7.             }); 
  8.         }); 
  9.     } 
  10.   
  11. quoteHandler.confirmCreate().then(createType => { 
  12.   
  13. }).catch(e => { 
  14.     // 這里能捕獲異常 
  15. }); 

而使用await,我們可以直接用同步的catch,就好像它真的變成同步執(zhí)行了:

 
 
 
 
  1. try { 
  2.     createType = await quoteHandler.confirmCreate("order"); 
  3. }catch(e){ 
  4.     console.log(e); 
  5.     return; 

總之使用await讓代碼少寫了很多嵌套,很方便的邏輯處理,縱享絲滑。

原文鏈接:https://fed.renren.com/2017/10/31/await/

【本文是專欄作者“人人網(wǎng)FED”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過(guò)聯(lián)系原作者獲取授權(quán)】

戳這里,看該作者更多好文


網(wǎng)頁(yè)名稱:如何使用Await減少回調(diào)嵌套
本文來(lái)源:http://m.jiaoqi3.com/article/dpjdcop.html