在日常浏览网页的过程中,我们经常会看到在使用chrome56以上版本访问一些涉及到用户帐号、密码之类含有敏感信息的页面时,chrome浏览器的地址栏里会出现“不安全”提示,如下图:
此时,我们采取的做法通常是把该页面开启https支持,通过https://yourdomain.com 来消除“不安全”提示,如下图:
具体的开启https的过程,本文就不深入去介绍了。
于是在实际的应用中,作为前端的我,噼里啪啦把页面所有“http://”改成“//”,然后高呼一声:大功告成,打完收工!
然鹅。。。打开chrome控制台一看,
chrome控制台警告:Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/.
这是什么鬼?完成看不懂!!!!此时度娘轻蔑地传来一声:叫你不好好读书,这句的意思是XMLHttpRequest同步请求占用了主线程,导致js进程发生阻塞。
受内伤的我于是高呼一声度娘你牛逼之后,赶紧扒开代码一看,果然在一个组件里发现了几个ajax是把async设置成了false的,意思是关闭了异步请求。那赶紧把async设为true呗,然后保存、刷新一看,咦,果然发现chrome的小叹号消失了,一抹亮丽的绿色像春天的嫩芽一样出现在chrome浏览器的头上,
完美解决!!
正当我洋洋得意再次刷新页面的时候,突然网络卡了一下,然后控制台爆出了一条红色的报错提示
赶紧查看刚才改动的ajax,发现其中一个$.each(arr,fun)的arr参数依赖它上面的ajax返回的数据,由于刚才把这个ajax的async改成了true异步请求数据,$.each()执行时arr还没有值传过来,于是报错!很好,知道问题在哪了,解决它易如反掌:把该each写到ajax的success回调函数里不就OK了吗?但再仔细看看each的上下文,发现它必须呆在ajax的外面,不能直接写到success回调里,这就尴尬了,顿时傻眼。。。
于是我再次汗颜,怎样解决上下文异步传值的问题????
功夫不负有钱人,通过度娘终于发现了“$.Deferred”这把杀猪刀。
上代码:
var dtd = $.Deferred();
$.ajax({
url: url,
type: 'GET',
async:true,
dataType: 'json',
cache: false
}).done(function(res){
...
dtd.resolve(res);
}).fail(function(jqXHR, textStatus, errorThrown) {
...
dtd.reject(jqXHR, textStatus, errorThrown);
});
if($.isArray(dtd)) {
var arr = dtd;
$.each(arr, function(index, val){
...`` });
}
这样通过Deferred作为管道,可以使因ajax若使用同步获取数据模式会占用js主进程导致chrome56以上会出现小叹号,若使用异步获取数据模式会导致下一步的业务逻辑因不能及时取到返回值而出现报错这两个矛盾的问题得到解决。
【总结】在给页面做https支持的时候,若遇到因ajax使用了同步请求而出现如上面的chrome浏览器出现小叹号提示的时候,请使用异步请求来解除js主线程的占用,消除小叹号。若业务逻辑需要必须使用同步请求,那么请尝试使用ajax设置为异步请求然后用Deferred来承载返回值的方法。
此外,Deferred的使用场所还有:
Ajax(XMLHttpRequest)
Image Tag,Script Tag,iframe(原理类似)
setTimeout/setInterval
CSS3 Transition/Animation
HTML5 Web Database
postMessage
Web Workers
Web Sockets
and more…