国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

流程控制: jQ Deferred 與 ES6 Promise 使用新手向入坑!

tomlingtm / 2408人閱讀

摘要:謝謝大大指出的關(guān)于中用的不到位的錯誤,貼上大大推薦的文章中的菜鳥和高階錯誤,文章很詳細(xì)說明了一些使用中的錯誤和指導(dǎo)。另外更正內(nèi)容在后面補(bǔ)充。從開始說到異步流程控制,之前用的比較多的是的。

謝謝n?i?g?h?t?i?r?e?大大指出的關(guān)于Promisecatch用的不到位的錯誤,貼上大大推薦的文章Promise中的菜鳥和高階錯誤,文章很詳細(xì)說明了一些Promise使用中的錯誤和指導(dǎo)。另外更正內(nèi)容在后面補(bǔ)充。

從 jQuery $.Deferred() 開始

說到異步流程控制,之前用的比較多的是jQ的Deferred。那Deferred是個啥呢,不清楚沒關(guān)系,直接控制臺來打印看下:

喔!看得出$.Deferred()后是個對象,其下面有著熟悉的done, fail, always字眼(對,,是不是有點(diǎn)熟悉了呢?沒錯!如果經(jīng)常用ajax的話就會經(jīng)常接觸到這些貨色)。 當(dāng)然了,不止這些,還有最最最重要的rejectresolve方法,說到這兩個方法,就得引出下Deferred的狀態(tài)機(jī)制了——其實很簡單,實例化后用上圖中的state方法就可以查看($.Deferred().state()),有三種狀態(tài)

執(zhí)行resolve/reject前,返回值是pending

執(zhí)行了resolve,返回值是resolved

執(zhí)行了reject,返回值是rejected

直接來試著用下吧!這里我們假設(shè)執(zhí)行一個隨機(jī)延時的setTimeout的異步操作,setTimeout異步操作結(jié)束后,根據(jù)延時大小,做出不同回應(yīng) ! 代碼:

function log (msg) {
    console.log(msg);
}
// 包裝一個異步操作
var Async = function () {
    // 生成一個0到5秒的延遲
    var delay = Math.floor(Math.random() * 5);
    // 創(chuàng)建一個Deffered對象
    var dfd = $.Deferred();
    // 這里調(diào)用一個異步操作
    setTimeout(function(){
        if (delay <= 2) {
            // 置dfd狀態(tài)為resolved
            dfd.resolve("一切正常!");
        } else {
            // 置dfd狀態(tài)為rejected
            dfd.reject("超時了!");
        }            
    }, delay * 1000)
    // 這里要返回Deferred下的promise對象Dererred對象的原因下面會解釋
    return dfd.promise();
}

Async()
    .done(function (data) {
        log(data) // 如果延遲不大于三秒 輸出dfd.resolve()中的數(shù)據(jù) "一切正常!"
    })
    .fail(function (err) {
        log(err) // 反之則 輸出dfd.reject()中的數(shù)據(jù) "超時了!" 
    })
    .always(function () {
        log("執(zhí)行完畢!"); // 總是輸出 "執(zhí)行完畢!"
    })
嘗試下通俗理解整個流程就是

在某個操作開始前創(chuàng)建一個Deferred對象,然后執(zhí)行操作

操作間可根據(jù)情況給dfd執(zhí)行relove或者reject方法改變狀態(tài)并傳入數(shù)據(jù)

最后返回出dfd的對象下的一個promise對象,這里不直接返回dfd對象是因為dfd對象的狀態(tài)是在第一次resolve或者reject后還可以更改的(不過里面的數(shù)據(jù)以第一次為準(zhǔn))!!

操作執(zhí)行后用donefail方法分別接受resolve和reject狀態(tài)和數(shù)據(jù)(一一對應(yīng))然后執(zhí)行回調(diào)(其實1.8還有個then方法,接受兩個參數(shù),第一個參數(shù)為resolve的回調(diào),第二個為reject的)

always是無論resolve還是reject都會執(zhí)行。

講個比較爛的比喻啊

我是一個流水線車間質(zhì)檢工人,就在平常的這樣的一天,來了一批玩具熊,嗯,接下來應(yīng)該是這樣的

來了一個檢查目標(biāo)($.Dererred()),這時你還不知道它是好是壞

我靠我?guī)资甑男聳|方炒菜技巧檢驗產(chǎn)品并給良品貼上了合格標(biāo)簽(dfd.res* olve(合格標(biāo)簽)),次品貼上回廠標(biāo)簽* (dfd.reject(回廠標(biāo)簽及原因)

然后通過的良品和次品都來到了各自的包裝口打好包,不能對里面的標(biāo)簽做更改了!(dfd.promise())去往自己下一個目的地(return dfd.promise)

再然后良品來到了熊孩子手中(.done()),次品回到了廠里(.fail()),最后不管玩具熊到了哪里,其實都會被開膛破肚(.always()好吧這里有點(diǎn)牽強(qiáng))

這里再上一張圖來解釋下!

還有值得說一下的是always里的回調(diào),我在實際中使用時發(fā)現(xiàn)總是在donefail里的回調(diào)(假設(shè)為同步)執(zhí)行完畢后后執(zhí)行的。

金掌銀掌仙人掌 掌聲有請 ES6 Promise

和上面一樣,先打印一下!

可以看到Promise下也有熟悉的resolvereject方法,好像和jQ的Deferred頗為相似!但是不是少了點(diǎn)什么呢?done或者fail之類的流程控制的方法呢??

不急,其實展開prototype原型上就可以看到掛載著的then方法了!(像極了jQ1.8后那個then,不過我覺得應(yīng)該說是jQ來遵循Promise才對)

Promise其實就是個構(gòu)造函數(shù),還是之前的例子,這里我們分三步走

var Async = function () {
    // 第一步,新建個promise對象,所需的異步操作在其中進(jìn)行
    var prms = new Promise(function(resolve, reject){
        // 生成一個0到5秒的延遲
        var delay = Math.floor(Math.random() * 5);
        // 這里調(diào)用一個異步操作
        setTimeout(function(){
            // 第二步, 根據(jù)情況置promise為resolve或者reject
            if (delay <= 2) {
                // 置dfd狀態(tài)為resolved
                resolve("一切正常!");
            } else {
                // 置dfd狀態(tài)為rejected
                reject("超時了!");
            }            
        }, delay * 1000)
    })
    // 第三步,返回這個Promise對象
    return prms
}

// 強(qiáng)大的來了
Async()
    // then接受兩個函數(shù)分別處理resolve和reject兩種狀態(tài)
    .then(
    function(data) {
        console.log(data) // 一切正常!
    }, 
    function(err) {
        console.log(err) // 超時了!!
    })

粗粗一看好像和Dererred不能更像了,,不過細(xì)心點(diǎn)的話可以發(fā)現(xiàn)我們在函數(shù)里直接返回了prms這個對象,而不是像之前把包裝了一層。。。對!因為Promise的特性就是一旦第一次賦予了狀態(tài)后面就無法更改了,這也算省心多了吧。但是問題來了,我為什么要選擇用Promise呢??

這么說吧,它是原生的 它是原生的 它是原生的!,還有可以鏈?zhǔn)芥準(zhǔn)芥準(zhǔn)芥準(zhǔn)秸{(diào)用!,我們可以把每一個then或者catch當(dāng)做一個處理器, 比如這樣

Async()
    // 這里暫時只處理resolve
    .then(function(data) {
        console.log(data) // 一切正常!
        return Promise.resolve("隨便什么");
    })
    // 下一個then處理器接收到上一個處理器發(fā)出的數(shù)據(jù)
    .then(function(data2) {
        console.log(data2) // 隨便什么
        return Promise.reject("錯誤數(shù)據(jù)");
    })
    ...

對!沒看錯,其實在then里面你還可以return其他的promise對象傳并遞數(shù)據(jù)!更有甚你甚至可以什么都不返回,比如說這樣

Async()
    .then(function(data) {
        console.log(data) // 一切正常!
    })
    // 上面那個處理器如果不return任何東西 就會默認(rèn)返回個resolve(undefined)
    // 然后下面的處理器就會接收到這個resolve(undefined)
    .then(function(data2) {
        console.log(data2) // undefined
        // 雖然沒有數(shù)據(jù)來處理,但是你還可以在這里做一些事情啊,例如
        return Promise.reject("錯誤數(shù)據(jù)");
    })
    // 嗒噠,catch就這么登場了,這里用catch處理上個then處理器發(fā)出的reject
    .catch(fucntion(err){
        console.log(err) // 錯誤數(shù)據(jù)
        return "那直接返回個字符串呢?"
    })
    // 上個catch處理器返回了個字符串其實也會被下個處理器接受
    // 相當(dāng)于resolve("那直接返回個字符串呢?")
    .then(function(data3){
        console.log(data3) // 那直接返回個字符串呢?
    })
    // 好,接著我們來試試在沒有返回任何東西的情況下接一個catch處理器
    .catch(function(err2){
        console.log(err2) 
        // 我們可以來猜一下上面會輸出什么,undefined嗎?
        // 錯,其實這里什么都不會輸出,因為這個catch接收的是resolve
        // 但它并不會吞沒這個resolve而是選擇跳過,例如我們這里再返回
        return Promise.resolve("這個字符串會被跳過")
    })
    // 這里緊接著個then處理器,它接受到的數(shù)據(jù)呢
    // 其實并不是上個catch返回的resolve("這個字符串會被跳過")
    // 而是catch之前那個then處理器默認(rèn)返回的resolve(undefined)
    .then(function(data4){
        console.log(data4) // undefined
    })

有點(diǎn)被繞暈了吧

我們用一句話來梳理下:

鏈?zhǔn)秸{(diào)下會有一串thencatch,這些thencatch處理器會按照順序接受上個處理器所產(chǎn)生的返回值,并且根據(jù)傳入的狀態(tài)做出不同響應(yīng),要么跳過,要么處理(所以上面23行處的catch處理器被跳過了)

ps: 上面我們用的then處理器只有一個函數(shù)參數(shù),所以只會處理resolve狀態(tài),如果是兩個then就可以處理reject了。

----更新于5月11日-----

catch使用的注意

上面一塊代碼中引出了catch處理器, 之前以為 cacth()then(null, ...) 的語法糖, 其實這么說不完全正確(功能層面上來說這兩個是完全相同的沒錯——都是處理reject和異常),但是到了實際使用中Promise中的菜鳥和高階錯誤文章中給出了明確的情況證明,這里貼一下:

首先只處理異常情況,下面兩個是等價的

somePromise().catch(function (err) {
  // 處理異常
});

somePromise().then(null, function (err) {
  // 處理異常
});

但是,如果不只是處理異常的下面兩種情況下就不一樣了

somePromise().then(function () {
  return otherPromise();
}).catch(function (err) {
  // 處理異常
});

somePromise().then(function () {
  return otherPromise();
}, function (err) {
  // 處理異常
});

不夠清楚嗎?那么如果是這樣呢?如果第一個回調(diào)函數(shù)拋出一個錯誤會發(fā)生什么?

somePromise().then(function () {
  throw new Error("這里錯了!");
}).catch(function (err) {
  console.log(err)
  // 這里錯了! :)
});

somePromise().then(
function () {
  throw new Error("這里錯了");
}, 
function (err) {
  console.log(err)
  // 未知 :(
  // 并沒有catch到上面那個Error
});

結(jié)論就是,當(dāng)使用 then(resolveHandler, rejectHandler)rejectHandler 不會捕獲在 resolveHandler 中拋出的錯誤!

貼完了,好吧,這有什么用呢?

看似這個注意項并不影響平常使用,原文作者也說道:

因為,筆者的個人習(xí)慣是從不使用then方法的第二個參數(shù),轉(zhuǎn)而使用 catch() 方法

那么,問題來了,如何正確的使用catch呢? 其實我沒有很好的想明白,希望指教,隨便拋兩個磚

// 1
somePromise()
    .then(resolveHandler)
    // 這個catch會處理somePromise或者resolveHandler的異常
    .catch(rejectHandler) 
    .then(otherResolveHandler)
    // 而這個catch呢只會處理resolveHandler的異常
    .catch(otherRejectHandler)
    
// 2
somePromise()
    .then(resolveHandler)
    .then(otherResolveHandler)
    // 至于這個catch則會處理somePromise、resolveHandler和otherResolveHandler的異常
    .catch(rejectHandler)
    
// 3 
somePromise()
    .catch(console.log.bind(console))
    //等價于
    .catch(function(err){
        console.log(err)
    })

哈哈哈哈哈哈,還是好好再去想想Promise去了,弄明白了再來補(bǔ)充,再次謝謝@n?i?g?h?t?i?r?e?大大,荊柯刺秦王

寫的很粗糙,有錯誤的地方希望多多指教!!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/79401.html

相關(guān)文章

  • 總結(jié)javascript基礎(chǔ)概念(二):事件隊列循環(huán)

    摘要:而事件循環(huán)是主線程中執(zhí)行棧里的代碼執(zhí)行完畢之后,才開始執(zhí)行的。由此產(chǎn)生的異步事件執(zhí)行會作為任務(wù)隊列掛在當(dāng)前循環(huán)的末尾執(zhí)行。在下,觀察者基于監(jiān)聽事件的完成情況在下基于多線程創(chuàng)建。 主要問題: 1、JS引擎是單線程,如何完成事件循環(huán)的? 2、定時器函數(shù)為什么計時不準(zhǔn)確? 3、回調(diào)與異步,有什么聯(lián)系和不同? 4、ES6的事件循環(huán)有什么變化?Node中呢? 5、異步控制有什么難點(diǎn)?有什么解決方...

    zhkai 評論0 收藏0
  • 面試題:沒有es6老項目,如何用jq解決異步的問題?

    摘要:我們都知道提供了異步寫法,但是大部分的公司都是寫的,那我們?nèi)绾斡脕韺懞彤惒揭粯拥膶懛剡@個知道的人不多下面我們就來寫寫把注意以上關(guān)鍵執(zhí)行完成已經(jīng)封裝好的員工定義執(zhí)行完成成功失敗返回最終返回使用員工對象這樣就可以使用了,其實的前身就是的,封 我們都知道es6提供了promise異步寫法,但是大部分的公司都是jq寫的,那我們?nèi)绾斡肑q來寫和promise異步一樣的寫法呢?這個知道的人不多下...

    hzx 評論0 收藏0
  • promise/deferred 模式原理分析和實現(xiàn)

    摘要:三模式模式其實包含兩部分和。六化在編碼的時候,想要用進(jìn)行異步操作流程控制,就要將當(dāng)前的異步回調(diào)函數(shù)封裝成。 一、什么是promise/deferred 模式 promise/deferred 模式是,根據(jù)promise/A 或者它的增強(qiáng)修改版promise/A+ 規(guī)范 實現(xiàn)的promise異步操作的一種實現(xiàn)方式。 異步的廣度使用使得回調(diào),嵌套出現(xiàn),但是一但出現(xiàn)深度的嵌套,就會讓codi...

    gclove 評論0 收藏0
  • 一篇文章帶你嘗試拿下js異步

    摘要:單線程就意味著,所有任務(wù)需要排隊,前一個任務(wù)結(jié)束,才會執(zhí)行后一個任務(wù)。這決定了它只能是單線程,否則會帶來很復(fù)雜的同步問題。小結(jié)本身是單線程的,并沒有異步的特性。當(dāng)異步函數(shù)執(zhí)行時,回調(diào)函數(shù)會被壓入這個隊列。 走在前端的大道上 本篇將自己讀過的相關(guān) js異步 的文章中,對自己有啟發(fā)的章節(jié)片段總結(jié)在這(會對原文進(jìn)行刪改),會不斷豐富提煉總結(jié)更新。 概念 JS 是單線程的語言。 單線程就意味著...

    MartinDai 評論0 收藏0
  • Angular $q 完全指南

    摘要:假設(shè)家具廠在一周后做完了這個衣柜,并如約送到了張先生家包郵哦,親,這就叫做衣柜,也就是已解決。這樣,整個異步流程就圓滿完成,無論成功或者失敗,張先生都沒有往里面投入任何額外的時間成本。 如果想使用 $http 或者其他異步操作, 那 $q 是必須要掌握的概念啦. Lets get started! 如何理解$q, deferred object ? 形象的講解angular中的$q與p...

    U2FsdGVkX1x 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<