产品的同事反映有时候浏览器会显示阻止了弹窗,问这是不是个bug 。

有一个笑话,测试人员直接说某个功能出现了bug,开发人员往往怀疑问题出在测试人员身上;而如果测试人员委婉一点说某个功能出现了意外的效果,是不是自己搞错了什么地方,开发人员直觉上会认为出现了bug。

当时我也是这样想的,我记得所有的弹窗用的代码都是 window.open(‘some_url’) ,如果有问题那就不会偶尔或者某个功能出现问题,应该所有地方出现问题才对,更何况我也有自测过,一次阻止弹窗的情况都没遇到过。

问她用的是什么浏览器,说是360。难道是360的问题?我们内部只需兼容 Chrome ,如果是这样就万事大吉了。不幸的是,她后来补充在 Chrome 上也遇到过。

问她 Chrome 的版本,比我的高,先升级到跟她一样的。

定位到出问题的功能,再跟别的没出过问题的功能两相比较,发现出问题的功能,打开新窗口的代码写在异步回调里。隐约觉得这就是问题所在。

先证实一下,把异步回调去掉,试了试,没问题;再把异步加回去,果然就显示阻止弹窗了。

到 stackoverflow 上找找答案(面向 stackoverflow 编程 逃……)原来浏览器会阻止所有不是由用户直接触发的弹窗。当回调代码执行时,由用户直接触发的那些代码早就返回了。

所以解决办法有两个:

  • 把异步变为同步,比如 ajax 请求加上 async: false ,只是这样会阻塞页面上其他代码执行

  • 先打开一个空白标签,在执行异步代码时通过设置空白标签的 window.location 属性把 url 改回去

实测第二种方法没有让用户觉察到什么不妥,于是最终就这样定下。改改测试用例就上了。

参考