事件起因

事情是这样的:产品上线发布,突然出现了问题。运营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

最后感谢老大威哥对露珠的鼓励,和帮助露珠查到的文档。

IOS9.0中hash值的bug与解决方案的更多相关文章

  1. Core 1.0中publishOptions Include的bug

    "publishOptions": { "include": [ "wwwroot", "Views", "A ...

  2. JS 中offset 的小bug 与解决方案。

    一.发现bug准备工作,先定义一个div,然后给div加上样式    效果图如图所示: 二.编写正常的代码,同时给div加上一个id     会发现div图会向左缩进...直至消失. 三.添加代码bo ...

  3. 开发中遇到的一些bug及解决方案

    一.在使用UIStackView时报“UIStackView before iOS 9.0”.

  4. ios开发之 -- stringByAddingPercentEscapesUsingEncoding方法被替换 iOS9.0

    最近在项目中,发现之前的一个方法已经不被建议使用了. 该方法名即题目中提到的: stringByAddingPercentEscapesUsingEncoding,这个方法是用来进行转码的,即将汉字转 ...

  5. 从客户端(ctl00$ContentPlaceHolder1$result="<?xml version="1.0" ...")中检测到有潜在危险的 Request.Form 值。

    ylbtech-Error-WebForm:从客户端(ctl00$ContentPlaceHolder1$result="<?xml version="1.0" . ...

  6. 判断修改的中的值,用前面的,否则容易获得空值;this.dataGridView1.Rows[i].Cells[0].EditedFormattedValue; VS bool b = (bool)this.dataGridView1.Rows[i].Cells[0].Value;

    判断修改的中的值,用前面的,否则容易获得空值:this.dataGridView1.Rows[i].Cells[0].EditedFormattedValue;  VS     bool b = (b ...

  7. MemSQL Start[c]UP 2.0 - Round 1 F - Permutation 思维+线段树维护hash值

    F - Permutation 思路:对于当前的值x, 只需要知道x + k, x - k这两个值是否出现在其左右两侧,又因为每个值只有一个, 所以可以转换成,x+k, x-k在到x所在位置的时候是否 ...

  8. Java 实现C#中的String.format效果 解决("我是{0},今年了","whaozl") bug

        /**      * 需要引入com.alibaba.fastjson.1.2.8      * 两种调用方式      * String template1="我是{0},今年{1 ...

  9. 整理iOS9适配中出现的坑(图文)

    原文: http://www.cnblogs.com/dsxniubility/p/4821184.html 整理iOS9适配中出现的坑(图文)   本文主要是说一些iOS9适配中出现的坑,如果只是要 ...

随机推荐

  1. Android MarginEnd与MarginStart (RTL)

    Android MarginLeft与MarginStart的区别http://blog.csdn.net/zhufuing/article/details/40181815 在写layout布局的时 ...

  2. python学习笔记-进程线程

    1.什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述 ...

  3. 手机端页面rem自适应脚本

    什么是rem 参照 web app变革之rem 在我看来,rem就是1rem单位就等于html节点fontsize的像素值.所以改变html节点的fontsize是最为关键的一步.根据手机宽度改变相对 ...

  4. js对象克隆方法

    方法1: function clone(obj){ var o; switch(typeof obj){ case 'undefined': break; case 'string' : o = ob ...

  5. ios 获取手机的IP地址

    - (NSString *)getIPAddress:(BOOL)preferIPv4{ NSArray *searchArray = preferIPv4 ? @[ IOS_VPN @"/ ...

  6. Stack Overflow: The Architecture - 2016 Edition(Translation)

    原文: https://nickcraver.com/blog/2016/02/17/stack-overflow-the-architecture-2016-edition/ 作者:Nick Cra ...

  7. activemq 控制面板里的 Number Of Pending Messages、 Messages Enqueued、Messages Dequeued含义

    Number Of Consumers  消费者 这个是消费者端的消费者数量 Number Of Pending Messages 等待消费的消息 这个是当前未出队列的数量.可以理解为总接收数-总出队 ...

  8. 配置apue的头文件apue.h和unp的头文件anp.h

    配置apue的头文件apue.h和unp的头文件anp.h 如果要使用gcc -g 来生成可调试文件一定要修改Make.defines.linux文件中的CFLAGS变量 修改为:CFLAGS=-an ...

  9. WebGL入门教程(三)-webgl动画

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL动画有移动.旋转和缩放,我们将移动.旋转和缩放图形,然后将其绘制到屏幕上,称为变换(tr ...

  10. Bug库

    netsh int tcp set global  ecn=disable C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe ...