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

資訊專欄INFORMATION COLUMN

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

Shimmer / 2205人閱讀

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

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

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

不要擴(kuò)展原生對象!

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

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

大多數(shù)開發(fā)者會告訴你:“不要擴(kuò)展原生對象”或者“只在polyfill的時候擴(kuò)展原生對象”。后者意味著只有當(dāng)擴(kuò)展的功能已經(jīng)被列入規(guī)范然后你只是為了能在舊的環(huán)境中使用這些功能的時候才能對元素對象進(jìn)行擴(kuò)展。

數(shù)組Push方法

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

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

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

乍一看可能覺得沒問題,但是你很快就會發(fā)現(xiàn)一些問題。

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

我們需要注意我們已經(jīng)破壞了數(shù)組對象for..in循環(huán)行為,因為我們的push(..)方法會出現(xiàn)在for..in循環(huán)的結(jié)果中。當(dāng)然,你不應(yīng)該在數(shù)組上使用for..in循環(huán),這又是另外一個話題了。

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

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

我們應(yīng)該問問我們自己,如果內(nèi)置的push(..)實現(xiàn)和我們的實現(xiàn)不兼容怎么辦?如果內(nèi)置的實現(xiàn)接受不一樣數(shù)量的參數(shù)或者不一樣的參數(shù)類型怎么辦?

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

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

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

Oops。

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

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

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

Promise擴(kuò)展

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

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

Blue In The Face

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

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

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

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

function someAsyncNonPromiseFunc() {
    // ...
}

var wrappedFn = Promise.method( someAsyncNonPromiseFunc );

var p = wrappedFn(..);

p.then(..)..;

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

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

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

未來約束

但是這還不是最糟的。如果Bluebir非常流行,然后許多現(xiàn)實中的網(wǎng)站依賴于這么一個擴(kuò)展,突然一天TC39協(xié)會通過某種方式強(qiáng)制避免擴(kuò)展官方規(guī)范,那么這些依賴于擴(kuò)展的網(wǎng)站都將崩潰。

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

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

包裝抽象

我認(rèn)為我們需要更多不破壞規(guī)范的polyfill,像我的"Native Promise Only"。我們需要良好,穩(wěn)固,性能優(yōu)秀但是和標(biāo)準(zhǔn)兼容的polyfill。

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

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

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

原生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來表達(dá)異步流程的難度的。它在底層實現(xiàn)為你創(chuàng)建promise,它自動把它們連接在一起,然后為同樣的組合模式提供了簡單的語法。

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

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

總結(jié)

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

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

最后,請負(fù)有責(zé)任感并且使用安全的promise擴(kuò)展。我們在將來會感謝你的。

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

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

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

    摘要:只要在調(diào)用異步函數(shù)時設(shè)置一個或多個回調(diào)函數(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

發(fā)表評論

0條評論

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