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

資訊專欄INFORMATION COLUMN

[譯] 深入理解 Promise 五部曲:4. 擴展問題

Shimmer / 2209人閱讀

摘要:有一個和相關的更大的問題。最后,請負有責任感并且使用安全的擴展。深入理解五部曲異步問題深入理解五部曲轉換問題深入理解五部曲可靠性問題深入理解五部曲擴展性問題深入理解五部曲樂高問題最后,安利下我的個人博客,歡迎訪問

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

現在,我希望你已經看過深入理解Promise的前三篇文章了。并且假設你已經完全理解Promises是什么以及深入討論Promises的重要性。

不要擴展原生對象!

回到2005年,Prototype.js框架是最先提出擴展Javascript原生對象的內置prototype屬性的框架之一。它們的想法是我們可以通過向prototype屬性添加額外的方法來擴展現有的功能。

如果你對近十年Javascript編程做一個簡單的調查,比如使用google簡單搜索下,你會發現對于這個想法有很多反對意見。它們都是有原因的。

大多數開發者會告訴你:“不要擴展原生對象”或者“只在polyfill的時候擴展原生對象”。后者意味著只有當擴展的功能已經被列入規范然后你只是為了能在舊的環境中使用這些功能的時候才能對元素對象進行擴展。

數組Push方法

想象一個真實的場景(確實發生在我身上):回到Netscape3/4和IE4的時代,當時的JS并沒有現在這么友好。作為許多顯著差異中的一個,數組并沒有push(..)方法來向它的尾部添加元素。

所以,一些人會通過下面這段代碼來擴展:

//Netscape 4 doesn"t hava Array.push
Array.prototype.push = function(elem){
    this[this.length - 1] = elem ;
}

乍一看可能覺得沒問題,但是你很快就會發現一些問題。

這里需要一個if來判斷原生是否有對于push(..)的支持,如果有我們就可以使用原生的push(..)方法。

我們需要注意我們已經破壞了數組對象for..in循環行為,因為我們的push(..)方法會出現在for..in循環的結果中。當然,你不應該在數組上使用for..in循環,這又是另外一個話題了。

有一個和1相關的更大的問題。不僅僅是需要一個if判斷:

if(!Array.prototype.push){
    //make our own
}

我們應該問問我們自己,如果內置的push(..)實現和我們的實現不兼容怎么辦?如果內置的實現接受不一樣數量的參數或者不一樣的參數類型怎么辦?

如果我們的代碼依賴于我們自己實現的push(..),然后我們只是簡單的用新的方法替換我們自己的方法,那么代碼會出現問題。如果我們的實現覆蓋了內置的push(..)實現,然后如果一些JS庫期望使用內置的標準push(..)方法怎么辦?

這些問題是真實發生在我身上的。我有一個工作是在一個用戶的古老的網站上加入一個組件,然后這個組件依賴于jQuery。我們組件在其他網站都可以正常使用,但是在這個特殊的站點卻無法使用。我花了很多時間來找出問題。
最終,我定位到了上面那個if代碼片段。這里有什么問題呢?

它的push(..)實現只接受一個參數,然而jQuery中期望是通過push(el1,el2,...)來調用push方法,所以它就無法正常運行了。

Oops。

但是猜猜當我移除原來的push代碼時發生了什么?在其他網站這個組件也不能使用的。為什么?我還是不知道具體是為什么。我認為他們意外地依賴于外部變量,而這些外部變量沒有傳遞進來。

但是,真正的問題是,有人通過一種對于未來存在潛在危險的方式擴展內置原生對象,導致這個方法在未來可能無法正常運行。

我不是唯一遇到這個問題的人。成千上萬的開發者都遇到了這種情況。我們中的大多數認為你必須十分小心當你擴展原生JS對象時。如果你這么做了,你最好不要使用跟語言新版本中的方法名相同的名字。

Promise擴展

為什么所有的老爺爺抱怨如今Promises的火熱呢?因為那些開發Promise"polyfills"的人似乎忘記或者拋棄了老人們的智慧。他們開始直接往PromisePromsie.prototype上加額外的東西。

我真的需要再去解釋為什么這是一個“未來的”壞點子嗎?

Blue In The Face

我們可以一直爭論這個問題到死,但是仍然不能改變這個事實。如果你擴展原生對象,你就是和未來敵對的,就算你覺得你自己已經做得很好了。

而且,你用越大眾化的名字來擴展原生對象,你越有可能影響未來的人。讓我們看看Bluebird庫,因為它是最流行的Promisepolyfill/庫之一。它足夠快但是它跟其他庫比起來也更加大。

但是速度和大小并不是我現在擔心的。我關心的是它選擇了把自己添加到Promise的命名空間上。就算它使用一個polyfill安全的方式,實際上并沒有,事實就算它添加許多額外的東西到原生對象上。

例如,Bluebird添加了Promise.method(..):

function someAsyncNonPromiseFunc() {
    // ...
}

var wrappedFn = Promise.method( someAsyncNonPromiseFunc );

var p = wrappedFn(..);

p.then(..)..;

看起來沒什么問題,是嗎?當然。但是如果某天規范需要添加Promise.method(..)方法。然后如果它的行為和Bluebird有很大的區別會怎么樣呢?

你又會看到Array.prototype.push(..)一樣的情況。

Bluebird添加了許多東西到原生的Promise。所以有很多可能性會在未來會發生沖突。我希望我從來不需要去修復某個人的Promise擴展代碼。但是,我很可能需要這么做。

未來約束

但是這還不是最糟的。如果Bluebir非常流行,然后許多現實中的網站依賴于這么一個擴展,突然一天TC39協會通過某種方式強制避免擴展官方規范,那么這些依賴于擴展的網站都將崩潰。

你看,這就是擴展原生對象的危險所在:你為了實現你的功能然后擴展原生對象,然后就拍拍屁股把這些爛攤子留給了TC39成員們。因為你愚蠢的決定Javascript的維護者只能選擇其他機制。

不相信我?這種情況已經發生很多次了。你知道為什么在19年的JS歷史中typeof null === "object"這個bug一直無法修復嗎?因為太多的代碼都依賴于這段代碼了。如果他們修復了這個bug,那么結果可想而知。
我真的不想這種事情發生在Promsie身上。請停止通過擴展原生對象來定義Promise polyfill/庫。

包裝抽象

我認為我們需要更多不破壞規范的polyfill,像我的"Native Promise Only"。我們需要良好,穩固,性能優秀但是和標準兼容的polyfill。

特別的,我們需要它們以便于那些需要擴展promise的人可以在這個包裝上進行操作。我們不應該很容易獲得一個Promisepolyfill然后創建我們自己的SuperAwesomePromise包裝在它上面嗎?

已經有很多的好例子了,比如Q和when,我自己也寫了一個,叫做asnquence(async + sequence),我的是設計來隱藏promises的,因為promise是低級別的API,所以與其給你一個簡單的抽象的東西不如隱藏丑陋的細節。

例如,比較下下面兩段代碼。

原生Promises:

function delay(n) {
    return new Promise( function(resolve,reject){
        setTimeout( resolve, n );
    } );
}

function request(url) {
    return new Promise( function(resolve,reject){
        ajax( url, function(err,res){
            if (err) reject( err );
            else resolve( res );
        } );
    } );
}

delay( 100 )
.then( function(){
    return request( "some/url" );
} )
.then(
    success,
    error
);

asynquence:

function delay(n) {
    return ASQ( function(done){
        setTimeout( done, n );
    } );
}

function request(url) {
    return ASQ( function(done){
        ajax( url, done.errfcb );
    } );
}

delay( 100 )
.val( "some/url" )
.seq( request )
.then( success )
.or( error );

希望你能夠通過這個簡單的例子看出asynquence是如何降低使用promises來表達異步流程的難度的。它在底層實現為你創建promise,它自動把它們連接在一起,然后為同樣的組合模式提供了簡單的語法。

顯然,我認為asynquence是非常令人驚奇的。我認為你應該看看一些例子,然后看看大家擴展的插件,這些插件使得它能提供更多的便利。

如果asynquence不是你的菜,那么你可以再尋找一個適合你的好用知名的抽象庫。
但是請不要使用那些擴展原生Promise的庫。這對于未來不是一件好事。

總結

Promise是令人驚奇的并且它們正在改變許多JS開發者編寫和維護一部流程的方式。ES6帶來的原生Promise是這個語言一個重大的勝利。為了加速這個勝利的過程,我們中的許多人開發Promise polyfill和Promise庫。

但是不要因為Promise帶來的興奮和喜悅讓你忘了一個不可否認的事實:擴展原生對象是一件危險并且充滿冒險的事情,并僅僅對于庫的作者也包括使用這些庫的所有人。

最后,請負有責任感并且使用安全的promise擴展。我們在將來會感謝你的。

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

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

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

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

相關文章

  • [] 深入理解 Promise 五部:1. 異步問題

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

    CHENGKANG 評論0 收藏0
  • [] 深入理解 Promise 五部:2. 控制權轉換問題

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

    alanoddsoff 評論0 收藏0
  • [] 深入理解 Promise 五部:3. 可靠性問題

    摘要:簡單的說,即將到來的標準指出是一個,所以作為一個,必須可以被子類化。保護還是子類化這是個問題我真的希望我能創建一個忠實的給及以下。 原文地址:http://blog.getify.com/promis... 如果你需要趕上我們關于Promise的進度,可以看看這個系列前兩篇文章深入理解Promise五部曲--1.異步問題和深入理解Promise五部曲--2.控制權轉移問題。 Promi...

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

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

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

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

    appetizerio 評論0 收藏0

發表評論

0條評論

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