• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

    ES7中利用Await減少回調(diào)嵌套的方法詳解

    來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:26:34
    文檔

    ES7中利用Await減少回調(diào)嵌套的方法詳解

    ES7中利用Await減少回調(diào)嵌套的方法詳解:前言 我們知道javascript是沒辦法阻塞的,所有的等待只能通過回調(diào)來完成,這就造成了回調(diào)嵌套的問題,導(dǎo)致代碼亂到爆,這時(shí)候Await就有用處了。 對(duì)于await的底層機(jī)制這里就不詳述了,以免將文章的篇幅拖的很長(zhǎng),需要的朋友們可以參考這篇文章://www.g
    推薦度:
    導(dǎo)讀ES7中利用Await減少回調(diào)嵌套的方法詳解:前言 我們知道javascript是沒辦法阻塞的,所有的等待只能通過回調(diào)來完成,這就造成了回調(diào)嵌套的問題,導(dǎo)致代碼亂到爆,這時(shí)候Await就有用處了。 對(duì)于await的底層機(jī)制這里就不詳述了,以免將文章的篇幅拖的很長(zhǎng),需要的朋友們可以參考這篇文章://www.g

    前言

    我們知道javascript是沒辦法阻塞的,所有的等待只能通過回調(diào)來完成,這就造成了回調(diào)嵌套的問題,導(dǎo)致代碼亂到爆,這時(shí)候Await就有用處了。

    對(duì)于await的底層機(jī)制這里就不詳述了,以免將文章的篇幅拖的很長(zhǎng),需要的朋友們可以參考這篇文章://www.gxlcms.com/article/123257.htm,下面開始本文的正式內(nèi)容。

    利用Await減少回調(diào)嵌套

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

    如下代碼所示:

    ajax({
     url: "/list",
     type: "GET",
     success: function(data) {
     appendToDOM(data);
     ajax({
     url: "/update",
     type: "POST",
     success: function(data) {
     util.toast("Success!");
     })
     });
     }
    });

    這樣的代碼看起來有點(diǎn)吃力,這種異步回調(diào)通常可以用Promise優(yōu)化一下,可以把上面代碼改成:

    new Promise(resolve => {
     ajax({
     url: "/list",
     type: "GET",
     success: data => resolve(data);
     })
    }).then(data => {
     appendToDOM(data);
     ajax({
     url: "/update",
     type: "POST",
     success: function(data) {
     util.toast("Successfully!");
     }) 
     }); 
    });

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

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

    let orderPromise = new Promise(resolve => {
     ajax("/order", "GET", data => resolve(data));
    });
    let userPromise = new Promise(resolve => {
     ajax("/user", "GET", data => resolve(data));
    });
    
    Promise.all([orderPromise, userPromise]).then(values => {
     let order = values[0],
     user = values[1];
    });

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

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

    // 使用await獲取異步數(shù)據(jù)
    let leadList = await new Promise(resolve => {
     ajax({
     url: "/list",
     type: "GET",
     success: data => resolve(data);
     });
    });
    
    // await讓代碼很自然地像瀑布流一樣寫下來 
    appendToDom(leadList);
    ajax({
     url: "/update",
     type: "POST",
     success: () => util.toast("Successfully");
    });

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

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

    let order = await new Promise(
     resolve => ajax("/order", data => resovle(data))),
    
     user = await new Promise(
     resolve => ajax("/user", data => resolve(data)));
    
    // do sth. with order/user

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

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

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

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

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

    let quoteHandler = {
     confirmCreate: function(){
     dialog.showDialog({
     contentTpl: tpl,
     className: "confirm-create-quote"
     });
     let $quoteDialog = $(".confirm-create-quote form")[0];
     return new Promise(resolve => {
     $(form.submit).on("click", function(event){
     resolve(form.createType.value);
     });
     });
     }
    
    }

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

    但是需要注意的是await的一次性執(zhí)行特點(diǎn)。相對(duì)于回調(diào)函數(shù)來說,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ì)有問題。

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

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

    npm install --save-dev babel-plugin-transform-async-to-generator

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

    {
     "plugins": ["transform-async-to-generator"]
    }

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

    require("babel-polyfill");

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

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

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

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

    function sleep (time) {
     return new Promise(resolve => 
     setTimeout(() => resolve(), time));
    }
    
    async function start () {
     await sleep(1000);
    }
    
    start();

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

    while (1) {
     switch (_context.prev = _context.next) {
     case 0:
     _context.next = 2;
     // sleep返回一個(gè)Promise對(duì)象
     return sleep(1000);
    
     case 2:
     case "end": 
     return _context.stop();
     }
    }

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

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

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

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

    let quoteHandler = {
     confirmCreate: function(){
     $(form.submit).on("click", function(event){
     // 這里會(huì)拋undefined異常:訪問了undefined的value屬性
     callback(form.notFoundInput.value);
     });
     }
    }
    
    try {
     // 這里無法捕獲到異常
     quoteHandler.confirmCreate();
    } catch (e) {
    
    }

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

    let quoteHandler = {
     confirmCreate: function(){
     return new Promise(resolve => {
     $(form.submit).on("click", function(event){
     // 這里會(huì)拋undefined異常:訪問了undefined的value屬性
     resolve(form.notFoundInput.value);
     });
     });
     }
    }
    
    quoteHandler.confirmCreate().then(createType => {
    
    }).catch(e => {
     // 這里能捕獲異常
    });

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

    try {
     createType = await quoteHandler.confirmCreate("order");
    }catch(e){
     console.log(e);
     return;
    }

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

    總結(jié)

    聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    ES7中利用Await減少回調(diào)嵌套的方法詳解

    ES7中利用Await減少回調(diào)嵌套的方法詳解:前言 我們知道javascript是沒辦法阻塞的,所有的等待只能通過回調(diào)來完成,這就造成了回調(diào)嵌套的問題,導(dǎo)致代碼亂到爆,這時(shí)候Await就有用處了。 對(duì)于await的底層機(jī)制這里就不詳述了,以免將文章的篇幅拖的很長(zhǎng),需要的朋友們可以參考這篇文章://www.g
    推薦度:
    標(biāo)簽: 回調(diào) 等待 嵌套
    • 熱門焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 最新国产在线精品观看| 久久精品国产久精国产思思| 亚洲午夜国产精品无码老牛影视 | 国产午夜精品理论片免费观看 | 3D动漫精品一区二区三区| 久久亚洲国产精品123区| 亚洲精品无码不卡| 经典国产乱子伦精品视频| 亚洲精品国产精品国自产观看 | 99精品人妻无码专区在线视频区 | 国产精品久久久久天天影视| 无码日韩精品一区二区三区免费| 精品国产人成亚洲区| 91精品国产色综久久| 99久久久精品免费观看国产| 久久精品水蜜桃av综合天堂| 中文字幕亚洲精品无码| 久久精品国产一区二区三区不卡| 成人精品视频成人影院| 欧美日激情日韩精品| 国产精品久久自在自线观看| 500av大全导航精品| 久久精品无码一区二区无码| 亚洲国产精品无码久久98| 亚洲性日韩精品国产一区二区 | 成人一区二区三区精品| 四虎国产精品永久地址51| 国产精品久久久天天影视| 92国产精品午夜福利| 精品少妇人妻av无码久久| 老司机午夜精品视频资源| 亚洲精品无码专区在线在线播放 | 国产精品久久久天天影视香蕉| 四虎4hu永久免费国产精品| 久久国产成人精品麻豆| 精品国产_亚洲人成在线高清| 国产99精品久久| 欧美大片日韩精品| 青青青青久久精品国产h| 2022精品国偷自产免费观看| 真实国产乱子伦精品免费|