成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[譯] 深入理解 Promise 五部曲:3. 可靠性問題

XboxYan / 1609人閱讀

摘要:簡單的說,即將到來的標(biāo)準(zhǔn)指出是一個(gè),所以作為一個(gè),必須可以被子類化。保護(hù)還是子類化這是個(gè)問題我真的希望我能創(chuàng)建一個(gè)忠實(shí)的給及以下。

原文地址:http://blog.getify.com/promis...

如果你需要趕上我們關(guān)于Promise的進(jìn)度,可以看看這個(gè)系列前兩篇文章深入理解Promise五部曲--1.異步問題和深入理解Promise五部曲--2.控制權(quán)轉(zhuǎn)移問題。

Promise狀態(tài) == 信任

在前面,我們說明了幾個(gè)關(guān)于Promises如何工作的要點(diǎn),這些要點(diǎn)是我們之所以可以信任promise機(jī)制作為控制轉(zhuǎn)移的一種解決方案的基礎(chǔ)。

這些要點(diǎn)直接來自Promises/A+規(guī)范。任何本地實(shí)現(xiàn)或者polyfill或者庫都必須通過一個(gè)全面嚴(yán)格的測試來確定是否符合規(guī)范。

對于promises可靠性是最基本的,因?yàn)槿绻麤]有可靠性,那么你就跟使用普通的回調(diào)一樣了。你必須謹(jǐn)慎地編寫那些涉及到異步調(diào)用第三方庫的代碼。你必須自己來解決狀態(tài)跟蹤的問題然后確保第三方庫不會出問題。

如果沒有可靠的promises你自己可以完成異步任務(wù)嗎?當(dāng)然可以。但是問題是,你自己無法處理得很完美,你得把很多額外的變量加到你的代碼中并且你會產(chǎn)生一個(gè)未來的維護(hù)風(fēng)險(xiǎn),代碼會變得很難維護(hù)。

Promises是被設(shè)計(jì)用來規(guī)范和集中這種邏輯的。你可以使用一個(gè)規(guī)范的promise系統(tǒng)而不用擔(dān)心可靠性問題,因?yàn)樗鼤凑誔romises機(jī)制來執(zhí)行。

可依賴嗎?

在理論上這個(gè)可靠性保證合同聽起來很棒。但是在JavaScript中真的有可能有這么一個(gè)機(jī)制嗎?

可靠性

在我開始說這個(gè)問題之前,我們首先排除一些JS代碼中的可靠性問題:

我們這里的討論跟密碼/加密中的“私有性”和“安全”無關(guān)。

和JS代碼可以被用戶通過查看源碼看到無關(guān)。

和一個(gè)黑客可以侵入你的服務(wù)器來發(fā)送一些惡意代碼或者通過中間人攻擊來劫持瀏覽器和服務(wù)器之間的連接來實(shí)現(xiàn)同樣的目的或者甚至在運(yùn)行時(shí)使用XSS漏洞來注入惡意代碼無關(guān)。

同時(shí),也和惡意代碼一旦存在你的頁面就可以理論上修改JavaScript運(yùn)行時(shí)功能(比如通過修改Object.prototype或者Function.prototype)來破壞你的程序這個(gè)事實(shí)無關(guān)。

相似的,和一些粗心的代碼可能會意外地通過非標(biāo)準(zhǔn)的方式來修改標(biāo)準(zhǔn)JS函數(shù)無關(guān)。

最后,和如果你頁面中依賴于第三方庫那么他們的服務(wù)器,連接和代碼也會出現(xiàn)上面所說的漏洞無關(guān)。

現(xiàn)在我可以繼續(xù)了,但是我認(rèn)為你已經(jīng)找到關(guān)鍵點(diǎn)了。我們在通過一個(gè)假設(shè)來縮小我們的討論范圍:當(dāng)所有的代碼以及主機(jī)環(huán)境都在一種預(yù)期的安全的狀態(tài)中時(shí),你的程序會如何執(zhí)行?

這并不是說我們使用Promise所做的事情對上面這些問題沒有幫助。這僅僅是由于這些問題在一個(gè)更高的層面上---這些問題遠(yuǎn)離了編寫API和模式,這些問題留給專家來討論。

在Promise狀態(tài)下的可靠性

我們看看下面這個(gè)例子:

var myPromise = {
    state: {
        status: 1,
        value: "Hello World"
    },
    then: function(success,failure) {
        // implement something like a thenable"s behavior
    }
};

我可以新建一個(gè)像這樣的對象,然后在平時(shí)使用它并且說我在用promises。實(shí)際是,我可以再完善一下使它可以通過整個(gè)Promises/A+ 測試網(wǎng)站的測試。

但是我真的是使用了Promises嗎?

你如何回答這個(gè)問題比你意識到的更重要。在很多開發(fā)者社區(qū)中很多人的回答是,是的。
我很確定的說,不是!

為什么?如果你通過了promises測試網(wǎng)站,那么它就是一個(gè)promise 了,不是嗎?而且,它在所有情況下都按照規(guī)范來執(zhí)行,不是嗎?

不是

promises的精髓遠(yuǎn)不是規(guī)范說的那么簡單,是可靠性。

可靠性是一個(gè)promise就是一個(gè)狀態(tài)(狀態(tài)會從"pending"轉(zhuǎn)變成"resolved"或者"rejected"其中一個(gè))的容器,這些狀態(tài)會附帶一個(gè)結(jié)果值(成功信息或者錯誤信息)。可靠性是一旦一個(gè)promise的狀態(tài)變?yōu)?resolved"或者"rejected",那么就不能改變也不會改變??煽啃跃褪峭瓿傻膒romise是不可變的。

但是promises的精髓還有一些更深層次的東西,這些是無法通過閱讀規(guī)范看出來的:改變一個(gè)promise狀態(tài)和設(shè)置它的完成值的能力只存在于原始的promise的實(shí)現(xiàn)。也就是說這個(gè)能力的實(shí)現(xiàn)掌握在開發(fā)者手里。

規(guī)范的早期版本中,把resolve/reject的功能分離出來放在一個(gè)對象中,叫做Deferred。把這想成一個(gè)對象對:在創(chuàng)建的時(shí)候,我們創(chuàng)建一個(gè)promise和一個(gè)deferred,deferred可以resolve這個(gè)promise。重要的是,這兩個(gè)可以被分開,一部分代碼可以resolve/reject一個(gè)promise而另外一部分只能監(jiān)聽這個(gè)變化然后做出回應(yīng)。

規(guī)范的后續(xù)版本中簡化了promises,通過刪除deferred對象,取而代之的是簡單的暴露出原來屬于deferred的resolve()reject()方法。

var p = new Promise( function(resolve,reject){
    // I have `resolve()` and `reject()` from the
    // hidden `deferred`, and I **alone** control
    // the state of the promise.
} );

// now, I can pass around `p` freely, and it can"t
// be changed by anyone else but the creator.

看看之前的那個(gè)myPromise對象。你注意到了什么嗎?

var myPromise = {
    state: {
        status: 1,
        value: "Hello World"
    },
    then: function(success,failure) {
        // implement something like a thenable"s behavior
    }
};

如果你到處傳遞myPromise,然后不管惡意代碼還是意外的代碼都可以改變myPromise.state.status或者myPromise.state.value屬性,我們是不是開了一個(gè)很大的后門,失去了Promises的可靠性。

當(dāng)然,答案是肯定的。把狀態(tài)暴露給方法使得這不是一個(gè)真正的promise。因?yàn)楝F(xiàn)在promise的保證已經(jīng)完全不可靠了。

如果你從一個(gè)第三方庫中得到了一個(gè)這樣的對象,你不會信任它的,不是嗎?更重要的,如果你把這個(gè)對象傳遞給其他第三方庫,你肯定不會相信只有原始的創(chuàng)建者才能修改它,不是嗎?

當(dāng)然不會相信。那就太天真了。

你看,使用promises是基于可靠性的。然后可靠性是基于promise的狀態(tài)是與外部影響隔離的,只有創(chuàng)建者能改變。注意到我并沒有說狀態(tài)必須是私有的,只要它不會被外界改變就可以。

如果沒有promise的對象不會被除了創(chuàng)建者改變的可靠性,那么promise就幾乎失去了它的意義。

錯誤的可靠性?

注意,這正是事情變得模糊的地方,是不可忽視的事實(shí)。

大多數(shù)為了在舊的JS環(huán)境下能夠支持promise的polyfill會把狀態(tài)通過可變的方式暴露出來。

Ouch!!!

在這方面,我的ES6 Promise polyfill"Native Promise Only"沒有把state暴露出來。據(jù)我所知,這是唯一一個(gè)沒有把promise狀態(tài)暴露出來的polyfill。
為什么?因?yàn)槲也粌H僅關(guān)心Promise規(guī)范,我更在意Promises的精髓。

Tradeoffs

但是究竟為什么所有這些高度可信的Promise polyfill和庫會忘了promise中這么重要的東西呢?因?yàn)樵谠鶭avascript有一些限制,這是一些內(nèi)置機(jī)制不需要遵循的。

簡單的說,即將到來的ES6標(biāo)準(zhǔn)指出Promise是一個(gè)“class”,所以作為一個(gè)“class”,promise必須可以被子類化。換句話說,你必須可以創(chuàng)建一個(gè)class CustomPromise extends Promise{..}子類,在這個(gè)基礎(chǔ)上你可以擴(kuò)展內(nèi)置promises的功能。

例如,你需要一個(gè)自定義的promise,這個(gè)promise可以處理超過一條消息。至少理論上,實(shí)現(xiàn)這個(gè)只需要你繼承內(nèi)置Promise類然后擴(kuò)展它。

鑒于我對JS中類概念的偏見,我認(rèn)為Promise子類化是一種沒有意義的鬧劇或者轉(zhuǎn)移注意力的幌子。我努力讓自己想出一些Promise子類化的好處,可是我實(shí)在想不出來。

而且,如果要繼續(xù)保持一些特性來遵循Promises/A+ Test Suite,這些子類的實(shí)現(xiàn)很可能變得相當(dāng)笨拙。

最后,我對于promise的子類化沒有任何好感。

怎么辦呢???

不涉及太多JS的細(xì)節(jié),把Promise表達(dá)成一個(gè)可以被繼承的"class"需要你把實(shí)例方法加入到Promise.prototype對象中。

但是當(dāng)你這么做的時(shí)候,你就把then..()catch(..)變成共享方法,所有Promise實(shí)例都可以訪問到,然后這些方法只能通過this訪問每個(gè)實(shí)例上的公共屬性。

換句話說,如果要使得promise可以子類化,只使用簡單的JS是不可能的,必須使用閉包或其他方法來為每個(gè)實(shí)例創(chuàng)建私有的promise狀態(tài)。

我知道現(xiàn)在你已經(jīng)開始想各種你見過的可以實(shí)現(xiàn)閉包私有和this公共繼承混合的方法。

我可以寫一整本書來說明為什么這樣行不通,但是我這里就簡單的說下:不要管你所聽到的,只使用ES5中可以使用的方法,你是不可能創(chuàng)建私有狀態(tài)同時(shí)又可以有效子類化的promise。

這兩個(gè)概念在ES5以下是互相排斥的。

Promise 削弱

另一個(gè)ES6中的新特性是WeakMap。簡單的說,一個(gè)WeakMap實(shí)例能夠使用對象引用作為鍵,然后和一個(gè)數(shù)據(jù)相聯(lián)系,而不需要真正把數(shù)據(jù)存儲在對象上。

這正是我們需要的,不是嗎?我們需要一個(gè)我們公共的then(..)catch(..)可以訪問的WeakMap,無論this綁定的是什么,它們都可以根據(jù)this訪問到并且查找對應(yīng)的被保護(hù)的狀態(tài)值。這個(gè)特權(quán)Promise方法可以取得這個(gè)內(nèi)部狀態(tài),但是外部不能。

不過,事情并沒有這么美好:

WeakMap根本不可能通過原生JS用性能可接受的方法實(shí)現(xiàn)。

就算我們在ES5及以下可以使用WeakMap,它還是沒有完全解決子類化的問題,因?yàn)槟惚仨氹[藏WeakMap實(shí)例使得只有你的Promise方法可以訪問,但是這樣的話另一個(gè)Promise的子類也能訪問到。

假設(shè)我們可以解決第二個(gè)問題---其實(shí)我們不能,就做一個(gè)假設(shè)。那么WeakMap的實(shí)現(xiàn)應(yīng)該是什么樣的呢?

var WeakMap = function(){
    var objs = [], data = [];

    function findObj(obj) {
        for (var i=0; i

OK,基本的思想就是我們維護(hù)兩個(gè)數(shù)組(objsdata),通過下標(biāo)相對應(yīng)。在第一個(gè)數(shù)組中保存對象引用,在另一個(gè)保存數(shù)據(jù)。

漂亮,不是嗎?

看看性能怎么樣吧??纯?b>findObj(..),它要循環(huán)整個(gè)數(shù)組來找到相應(yīng)的數(shù)據(jù)。引用越多性能就越低。

但是這還不是最壞的地方。WeakMap之所以叫做“Weak”是由于垃圾回收行為。在我們WeakMap的實(shí)現(xiàn)中,會保存每個(gè)對象的引用,這就意味著就算程序已經(jīng)沒有對于對象的引用了,這些對象還是不能被回收。但是真正的WeakMap就是這么“weak”,所以你不需要做任何事情來優(yōu)化垃圾回收。

好的,WeakMap是一個(gè)錯誤的希望。它并沒有解決ES6中的問題并且使得事情在ES5及以下變得更糟。

保護(hù)state還是子類化?

這是個(gè)問題!

我真的希望我能創(chuàng)建一個(gè)忠實(shí)的Peomisepolyfill給ES5及以下。但是必須做一個(gè)選擇,在這里出現(xiàn)了一個(gè)分歧。要不就放棄子類化的功能,要不就放棄作為promise的可靠性。

那么我們該怎么做呢?

總結(jié)

我會做另一個(gè)promise polyfill,這個(gè)polyfill選擇保留子類化的能力,以可變的state為代價(jià)。

我已經(jīng)選擇了拋棄子類化使得我的promise polyfill可以很可靠。就像我之前說的,我認(rèn)為promise的子類化最終會被證明是一個(gè)華而不實(shí)的東西。我不會犧牲promise的可靠性來順從子類化。

很顯然,其他人對于這個(gè)問題會有不同的看法。但是我只想讓你問問你自己:一個(gè)不可靠的promise可以用來干嘛?什么代碼能真正拯救你?什么代碼可以做得更好?

現(xiàn)有的Promise polyfill和庫的問題比不可變的state vs 子類化更深層面。在第四部分:擴(kuò)展問題中,我會指出許多現(xiàn)有polyfill和庫中的問題。

譯者注

這篇文章不大好翻譯也不大好理解,所以在這里總結(jié)下我的理解,希望對大家的理解有所幫助,如果大家有什么不同的看法,歡迎討論。

這篇文章圍繞Promise的可靠性展開,Promise的可靠性是它的精髓所在。要實(shí)現(xiàn)Promise的可靠性最關(guān)鍵的就是要保證Promise的狀態(tài)值state不能被外部改變,這樣才能保證狀態(tài)值的不可逆。

而現(xiàn)在幾乎所有的Promise庫都忽略了這個(gè)關(guān)鍵,而它們會忽略這個(gè)關(guān)鍵點(diǎn)一個(gè)很重要的原因就是在ES6的規(guī)范中,Promise被規(guī)定為一個(gè)類,也就是說Promise是可以被子類化的。然而在ES5及以下的規(guī)范中,在沒有private關(guān)鍵字的情況下,是不可能實(shí)現(xiàn)可子類化同時(shí)又能保證Promise的狀態(tài)值不會被外部改變(真的嗎?我保持懷疑態(tài)度)。而在ES6中出現(xiàn)的新對象WeakMap確實(shí)給實(shí)現(xiàn)Promise帶來了新的思路,可以在ES5及以下環(huán)境中實(shí)現(xiàn)WeakMap,利用它的特點(diǎn)可以實(shí)現(xiàn)符合要求的Promise。具體實(shí)現(xiàn)思路就是:定義一個(gè)全局私有的WeakMap,這個(gè)WeakMap只有公共的方法then()catch()可以訪問到,在這個(gè)WeakMap中以每個(gè)Promise實(shí)例的this作為鍵,狀態(tài)值state作為值進(jìn)行存儲。這樣在每個(gè)Promise實(shí)例中都可以通過自己的this對象查找自己的狀態(tài)值,而不能查找到其他Promise實(shí)例的狀態(tài)值,這樣就實(shí)現(xiàn)了狀態(tài)值的外部不可修改。但是WeakMap有一個(gè)很大的問題就是性能比較低并且不利于垃圾回收,所以這并不是一個(gè)理想的解決方案。

綜上兩個(gè)原因就導(dǎo)致了現(xiàn)在大部分庫暴露state狀態(tài)值,它們?yōu)榱藢?shí)現(xiàn)子類化選擇了暴露狀態(tài)值,丟棄了Promise的精髓所在。

而在作者看來子類化對于Promise的重要性遠(yuǎn)遠(yuǎn)比不上Promise的可靠性,所以它選擇了放棄子類化而保證Promise的可靠性。事實(shí)確實(shí)是這樣,如果不能保證Promise的可靠性,那么就會出現(xiàn)第一篇中出現(xiàn)的那個(gè)不可靠的情況,這樣Promise除了改善了回調(diào)金字塔的問題,跟普通的回調(diào)也就沒有什么區(qū)別了,也就失去了它更重要的意義。

深入理解Promise五部曲--1.異步問題
深入理解Promise五部曲--2.轉(zhuǎn)換問題
深入理解Promise五部曲--3.可靠性問題
深入理解Promise五部曲--4.擴(kuò)展性問題
深入理解Promise五部曲--5.樂高問題

最后,安利下我的個(gè)人博客,歡迎訪問:http://bin-playground.top

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/87559.html

相關(guān)文章

  • [] 深入理解 Promise 五部:2. 控制權(quán)轉(zhuǎn)換問題

    摘要:直到最近,我們?nèi)匀辉谟煤唵蔚幕卣{(diào)函數(shù)來處理異步的問題。當(dāng)我們只有一個(gè)異步任務(wù)的時(shí)候使用回調(diào)函數(shù)看起來還不會有什么問題。 原文地址:http://blog.getify.com/promis... 廈門旅行歸來,繼續(xù)理解Promise 在上一篇深入理解Promise五部曲:1.異步問題中,我們揭示了JS的異步事件輪詢并發(fā)模型并且解釋了多任務(wù)是如何相互穿插使得它們看起來像是同時(shí)運(yùn)行的。...

    alanoddsoff 評論0 收藏0
  • [] 深入理解 Promise 五部:1. 異步問題

    摘要:當(dāng)引擎開始執(zhí)行一個(gè)函數(shù)比如回調(diào)函數(shù)時(shí),它就會把這個(gè)函數(shù)執(zhí)行完,也就是說只有執(zhí)行完這段代碼才會繼續(xù)執(zhí)行后面的代碼。當(dāng)條件允許時(shí),回調(diào)函數(shù)就會被運(yùn)行。現(xiàn)在,返回去執(zhí)行注冊的那個(gè)回調(diào)函數(shù)。 原文地址:http://blog.getify.com/promis... 在微博上看到有人分享LabJS作者寫的關(guān)于Promise的博客,看了下覺得寫得很好,分五個(gè)部分講解了Promise的來龍去脈。從...

    CHENGKANG 評論0 收藏0
  • [] 深入理解 Promise 五部:4. 擴(kuò)展問題

    摘要:有一個(gè)和相關(guān)的更大的問題。最后,請負(fù)有責(zé)任感并且使用安全的擴(kuò)展。深入理解五部曲異步問題深入理解五部曲轉(zhuǎn)換問題深入理解五部曲可靠性問題深入理解五部曲擴(kuò)展性問題深入理解五部曲樂高問題最后,安利下我的個(gè)人博客,歡迎訪問 原文地址:http://blog.getify.com/promis... 現(xiàn)在,我希望你已經(jīng)看過深入理解Promise的前三篇文章了。并且假設(shè)你已經(jīng)完全理解Promises...

    Shimmer 評論0 收藏0
  • 在 PHP 中使用 Promise + co/yield 協(xié)程

    摘要:只要在調(diào)用異步函數(shù)時(shí)設(shè)置一個(gè)或多個(gè)回調(diào)函數(shù),函數(shù)就會在完成時(shí)自動調(diào)用回調(diào)函數(shù)。要解決的問題是,如何將回調(diào)方法的參數(shù)從回調(diào)方法中傳遞出來,讓它可以像同步函數(shù)的返回結(jié)果一樣,在回調(diào)函數(shù)以外的控制范圍內(nèi),可以傳遞和復(fù)用。 摘要: 我們知道 JavaScript 自從有了 Generator 之后,就有了各種基于 Generator 封裝的協(xié)程。其中 hprose 中封裝的 Promise 和...

    appetizerio 評論0 收藏0
  • [] 深入理解 Promise 五部:5. LEGO

    摘要:一個(gè)就像一個(gè)樂高玩具。問題是不是你小時(shí)候玩兒的那個(gè)有趣,它們不是充滿想象力的打氣筒,也不是一種樂高玩具。這是對的并不是給開發(fā)者使用的,它們是給庫作者使用的。不會超過這兩種情況。第二個(gè)是根據(jù)第一個(gè)處理函數(shù)如何運(yùn)行來自動變成狀態(tài)成功或者失敗。 原文地址:http://blog.getify.com/promis... 在 Part4:擴(kuò)展問題 中,我討論了如何擴(kuò)展和抽象Promise是多么...

    LiveVideoStack 評論0 收藏0

發(fā)表評論

0條評論

XboxYan

|高級講師

TA的文章

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