IOS9.0中hash值的bug與解決方案

事件起因

事情是這樣的:產品上線發佈,突然出現了問題。運營Gg過來反應,當場給露珠演示,運營同事的手機是iphone,bug確實是存在的。奇怪的是露珠用了其他iphone手機(借別人的,露珠的是吊死安卓機),卻沒有發現這個問題。仔細詢問,同事說他最近剛剛升級的ios9,於是問題最初定位在操作系統上。接下來檢查代碼,發現運行正常,邏輯也沒錯。問題就卡到這裏了。沒辦法,線上問題,fiddler替換本地腳本調試,一級一級alert,從項目文件到底層庫,最後定位到了backbone。查看backbone源碼,發現問題結症:_updateHash方法中有改變hash值的方法,location.hash和location.replace兩個,不管執行的是哪個,hash值不會立即改變!也就是說早ios9中hash在地址欄中變化有延遲!

backbone的hash跳轉機制

一、代碼層:在backbone(以下簡稱bk)中,利用的是route.navigate方法進行路由的跳轉,bk框架會根據你傳入的hash值,手動替換地址欄中的hash,接着調用loadUrl方法去內存中讀取傳入的路由配置,執行回掉函數。大概流程類似如下代碼:

route.navigate(手動調用跳轉)--->_updateHash(更新地址欄中的url)->loadUrl(去內存中讀取註冊的路由事件)->callback(執行回掉函數);

二、瀏覽器層:瀏覽器層是不受代碼控制的,但是瀏覽器提供給了js監聽url的事件,現代瀏覽器中都支持onhashchange事件,當然,這你也可以在start中配置默認採用popstate事件監聽,如果是老舊的瀏覽器,bk採取的是定時器時刷新的監聽方式。不管哪一種方式,都是爲了檢測地址欄中hash值得變化。通過瀏覽器的回退和前進功能,hash值會跟隨變化,而瀏覽器本身不會刷新,所以,通過各種對url變化事件的監聽,可以做到響應自定義的事件。大概流程類似如下的代碼:

back/forward(瀏覽器前進或者後退)------>onhashchange(出發hash值變化)----->checkUrl(執行loadUrl之前檢測url,該方法主要應付的事瀏覽器的行爲,代碼層則會return)---->loadUrl(通過查找內存找到對應路由的回掉)---->callback(執行自定義回掉函數);

一切都井井有條地進行着,直到ios9的發佈,而你們這羣有錢人又急着把自己的果機升級。結果是,如果你在回掉函數中需要處理url的話,那麼你得到的是舊的url不會是最新的。

補救和兼容

爲了查找結症,露珠在百度無果後google到了同樣在這方面遇到的問題的同行。沒想到爲了這個bug,老外在github上炸開了鍋,各種吐槽ios9,不管是bk或者anglar都存的開發者都遇到了這個hash改變延遲的問題。然後還有的大神給出瞭解決的方案(鏈接在文章末尾中露珠會發出來)。同時滷煮爲了驗證,自己在ios9真機上調試了。以下是露珠的代碼調試和輸出的結果,問題都出在_updateHash這個方法上面:

爲了解決延遲問題,我們的方案當然也是延遲。通過測試,hash值的變化大概在ios9下游9~30ms(一次一次地alert結果,不太準確),所以,我們可以將回掉函數延遲>30ms時間執行。我們把loadUrl延遲了大概50ms,50ms對於用戶來說是一個很短的過程,所以,對於那些沒有出毛病的系統來說也是可以接受的。於是,我們把源碼(1599行左右)改成一下面這樣的:

if (options.trigger) {
        var self = this;//this存入全局變量中
        setTimeout(function(){//延遲50ms執行
          return self.loadUrl(fragment);
        }, 50);
 }

通過檢測,通過了各個系統的測試。目前還是比較穩定。

結語

露珠堅持不動框架源碼的原則,不在萬不得已的情況下堅決不動框架源碼。但是一旦出現了類似系統的bug,爲了修復,修改源碼也是一種無奈。蘋果這種大公司,一個小bug可能牽動的是全球成千上萬的開發者。希望蘋果公司早日修復此bug。而不是要我們這些開發者寫兼容。同時也希望露珠的博客對於正在開發bk或者其他單頁面應用的讀者諸君有些許的幫助。

參考文檔

https://github.com/driftyco/ionic/commit/e5b85dfc47dee788382c7da8f3a8abed7c2d38ac

https://github.com/angular/angular.js/issues/12241

最後感謝老大威哥對露珠的鼓勵,和幫助露珠查到的文檔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章