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

資訊專欄INFORMATION COLUMN

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

XboxYan / 1599人閱讀

摘要:簡單的說,即將到來的標準指出是一個,所以作為一個,必須可以被子類化。保護還是子類化這是個問題我真的希望我能創建一個忠實的給及以下。

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

如果你需要趕上我們關于Promise的進度,可以看看這個系列前兩篇文章深入理解Promise五部曲--1.異步問題和深入理解Promise五部曲--2.控制權轉移問題。

Promise狀態 == 信任

在前面,我們說明了幾個關于Promises如何工作的要點,這些要點是我們之所以可以信任promise機制作為控制轉移的一種解決方案的基礎。

這些要點直接來自Promises/A+規范。任何本地實現或者polyfill或者庫都必須通過一個全面嚴格的測試來確定是否符合規范。

對于promises可靠性是最基本的,因為如果沒有可靠性,那么你就跟使用普通的回調一樣了。你必須謹慎地編寫那些涉及到異步調用第三方庫的代碼。你必須自己來解決狀態跟蹤的問題然后確保第三方庫不會出問題。

如果沒有可靠的promises你自己可以完成異步任務嗎?當然可以。但是問題是,你自己無法處理得很完美,你得把很多額外的變量加到你的代碼中并且你會產生一個未來的維護風險,代碼會變得很難維護。

Promises是被設計用來規范和集中這種邏輯的。你可以使用一個規范的promise系統而不用擔心可靠性問題,因為它會按照Promises機制來執行。

可依賴嗎?

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

可靠性

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

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

和JS代碼可以被用戶通過查看源碼看到無關。

和一個黑客可以侵入你的服務器來發送一些惡意代碼或者通過中間人攻擊來劫持瀏覽器和服務器之間的連接來實現同樣的目的或者甚至在運行時使用XSS漏洞來注入惡意代碼無關。

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

相似的,和一些粗心的代碼可能會意外地通過非標準的方式來修改標準JS函數無關。

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

現在我可以繼續了,但是我認為你已經找到關鍵點了。我們在通過一個假設來縮小我們的討論范圍:當所有的代碼以及主機環境都在一種預期的安全的狀態中時,你的程序會如何執行?

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

在Promise狀態下的可靠性

我們看看下面這個例子:

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

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

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

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

為什么?如果你通過了promises測試網站,那么它就是一個promise 了,不是嗎?而且,它在所有情況下都按照規范來執行,不是嗎?

不是

promises的精髓遠不是規范說的那么簡單,是可靠性

可靠性是一個promise就是一個狀態(狀態會從"pending"轉變成"resolved"或者"rejected"其中一個)的容器,這些狀態會附帶一個結果值(成功信息或者錯誤信息)。可靠性是一旦一個promise的狀態變為"resolved"或者"rejected",那么就不能改變也不會改變。可靠性就是完成的promise是不可變的。

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

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

規范的后續版本中簡化了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.

看看之前的那個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屬性,我們是不是開了一個很大的后門,失去了Promises的可靠性。

當然,答案是肯定的。把狀態暴露給方法使得這不是一個真正的promise。因為現在promise的保證已經完全不可靠了。

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

當然不會相信。那就太天真了。

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

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

錯誤的可靠性?

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

大多數為了在舊的JS環境下能夠支持promise的polyfill會把狀態通過可變的方式暴露出來。

Ouch!!!

在這方面,我的ES6 Promise polyfill"Native Promise Only"沒有把state暴露出來。據我所知,這是唯一一個沒有把promise狀態暴露出來的polyfill。
為什么?因為我不僅僅關心Promise規范,我更在意Promises的精髓。

Tradeoffs

但是究竟為什么所有這些高度可信的Promise polyfill和庫會忘了promise中這么重要的東西呢?因為在原生Javascript有一些限制,這是一些內置機制不需要遵循的。

簡單的說,即將到來的ES6標準指出Promise是一個“class”,所以作為一個“class”,promise必須可以被子類化。換句話說,你必須可以創建一個class CustomPromise extends Promise{..}子類,在這個基礎上你可以擴展內置promises的功能。

例如,你需要一個自定義的promise,這個promise可以處理超過一條消息。至少理論上,實現這個只需要你繼承內置Promise類然后擴展它。

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

而且,如果要繼續保持一些特性來遵循Promises/A+ Test Suite,這些子類的實現很可能變得相當笨拙。

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

怎么辦呢!?

不涉及太多JS的細節,把Promise表達成一個可以被繼承的"class"需要你把實例方法加入到Promise.prototype對象中。

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

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

我知道現在你已經開始想各種你見過的可以實現閉包私有和this公共繼承混合的方法。

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

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

Promise 削弱

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

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

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

WeakMap根本不可能通過原生JS用性能可接受的方法實現。

就算我們在ES5及以下可以使用WeakMap,它還是沒有完全解決子類化的問題,因為你必須隱藏WeakMap實例使得只有你的Promise方法可以訪問,但是這樣的話另一個Promise的子類也能訪問到。

假設我們可以解決第二個問題---其實我們不能,就做一個假設。那么WeakMap的實現應該是什么樣的呢?

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

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

OK,基本的思想就是我們維護兩個數組(objsdata),通過下標相對應。在第一個數組中保存對象引用,在另一個保存數據。

漂亮,不是嗎?

看看性能怎么樣吧。看看findObj(..),它要循環整個數組來找到相應的數據。引用越多性能就越低。

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

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

保護state還是子類化?

這是個問題!

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

那么我們該怎么做呢?

總結

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

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

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

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

譯者注

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

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

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

綜上兩個原因就導致了現在大部分庫暴露state狀態值,它們為了實現子類化選擇了暴露狀態值,丟棄了Promise的精髓所在。

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

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87559.html

相關文章

  • [] 深入理解 Promise 五部:2. 控制權轉換問題

    摘要:直到最近,我們仍然在用簡單的回調函數來處理異步的問題。當我們只有一個異步任務的時候使用回調函數看起來還不會有什么問題。 原文地址:http://blog.getify.com/promis... 廈門旅行歸來,繼續理解Promise 在上一篇深入理解Promise五部曲:1.異步問題中,我們揭示了JS的異步事件輪詢并發模型并且解釋了多任務是如何相互穿插使得它們看起來像是同時運行的。...

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

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

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

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

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

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

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

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

    LiveVideoStack 評論0 收藏0

發表評論

0條評論

XboxYan

|高級講師

TA的文章

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