Published on
1092

React 组件开发中 iframe 请求被取消

Authors
  • avatar
    Name
    小辉辉
    Twitter

前言

前端开发虽说上手容易,但是难的是什么?疑难问题,那种没有被写进常规API里面的问题,碰到这种问题排查起来特别麻烦,有时候只能靠无数个假设再去验证,时间也是这样就过去了,若是后面找到原因了,要是找不到真的闹心啊。

所以我决定对每个诡异的问题都做个记录,不仅仅是方便自己后面来回顾,也方便给后面遇到有同样问题的朋友。

这次的问题很简单,就是有个React组件里面,里面返回一个iframe元素,这个组件接收一个url参数作为iframe元素的地址。

这个简单的组件一直运行的很正常,直到上周有个人在用的过程中发现了问题,这个iframe不加载内容了!

排查

这种问题我以前也是遇到过的,当时有个场景,先是加载了iframe元素,在很短的一个时间内,这个iframe元素被删除了,我们就在控制台能够明显看到iframe对应src地址被cancelled的现象。

这个情况倒好理解,但是这次的情况不一样,页面上iframe元素还在呢,而且src属性也在也是正确的,但是网络请求就是出现了cancelled这个状态。

我当时想的是什么呢?马上去看这个组件的修改记录,看了一圈没有啊,而且按照用户使用的场景也配置了一个相同的,但是硬是没有复现,也是正常加载的。

这时候就没办法了,只能硬头皮去看组件的实现代码了,核心代码真的很简单,组件首次加载会将iframe隐藏,等到组件加载完毕后,会设置一个state更新iframe对应的src地址,同时iframe会配置一个onload事件,等到加载完成后再次更新一个state显示iframe元素。

看了好几遍,完全看不出有啥问题,这让人奇怪的就是那个用户的页面有问题,现在的我已经走入到调试react源代码了,我的猜测是项目的其他地方的代码导致了iframe元素做了什么从页面上移除又重新插入到页面元素上的操作。

在react中打了两处断点,一个是创建iframe元素的地方,一个是更新src属性的地方,两个地方全部验证正常没有问题,眼看着一上午时间又快过去了,这时候用户还来问题解决了没有?

中间也想过问下AI是不是还有啥我没有考虑到的场景,看了看都不是我的情况。

这个时候突然注意到一个情况,跟这个页面同样结构的还有个页面,我试着看看的心态访问了那个页面,这时候突然在控制台看到了一个万万没有想到的报错信息,简单讲就是某个元素没有找到。

仔细在看那段代码如下

document.getElementById('xxx').firstChild.contentWindow.location.reload();

上面这段代码中的firstChild就是这个组件里返回的iframe元素,而这段代码是什么时候调用的呢?就是在这个页面加载完成后运行的。

那这样就很能解释的通了,我们设想下基本情况应该是这样的,react显示给页面iframe元素更新了src属性,之后立马运行上述的reload方法,这时是不是就很有可能出现上面提到的请求被cancelled的情况呢?

马上把下面的代码在控制台运行了下

var e = document.createElement('iframe');
document.body.appendChild(e);
e.setAttribute(src, 'xxxxx');

// 下面马上调用iframe元素内部window的reload方法

e.contentWindow.location.reload();

果然上述代码运行后iframe在页面上没有显示,网络出现了cancelled的请求。

结局

事情到这里,一切都清楚了,可想而知,如果我们没有去查看那个页面的想法,这个问题估计没这块能解决,这样给我后面排查提供了一个新思路,还是要多多考虑项目代码之外的第三方代码的情况。