Reflect反射的兼容问题
页面中执行 fet-block-logic.js,sentry监控会发现忽然上涨如下这样的报错:
主要有2个问题:
- Falled to construct "XMLHttpRequest: Please use the 'new' operator, this DoM object constructor cannot be called as a function
- t._resetXhrUnset is not a function, t._resetXhrToUnset is undefined
问题1看起来像是有人通过直接函数调用的方式使用了 window.XMLHttpRequest,而window.XMLHttpRequest是构造函数,需要使用 new 来调用。 然而为什么只有我们的代码发布后才会产生这种报错呢?这说明肯定也跟我们代码有关。
问题2看起来是我们的自己实现的FetXMLHttpRequest类中,调用自身方法时候,报了不存在该方法。仔细回看了下代码,我们代码都是在自己的class内部通过 this 来调用,理论上不应该出现这种错误。难道是有人在使用我们的XHR class的时候,强行改掉了我们某些函数的this指向。
下面我们来分析这2个问题。
分析问题1
DANGER
Falled to construct "XMLHttpRequest: Please use the 'new' operator
该问题看起来主要发生在 chrome50及其以下的安卓机器,于是我们找到一台 chrome 43的安卓5进行复现。发现确实可以复现。复现后开始debug打日志,看看到底是哪一个步骤出现问题。最终找到
解决rollup编译后类继承时的机型兼容问题
sentry部分安卓5机型(都是chrome小于等于50内核)出现报错:
Failed to construct 'XMLHttpRequest': Please use the 'new' operator
部分ios小于等于13机型报出:
function _resetXhrUnset is undefined
经过实际分析,发现:
- 安卓报错原因,是因为其不支持 Reflect但是 rollup 构建结果判定时
找到真正的 XHR
js
function getNativeXHr() {
let xhrProto = window.XMLHttpRequest.prototype
while(Object.getPrototypeOf(xhrProto) !== XMLHttpRequestEventTarget.prototype) {
xhrProto = Object.getPrototypeOf(xhrProto);
}
return xhrProto.constructor
}
为了防止上述函数死循环,我们这样进行xhrProto的兜底处理:
js
function getNativeXHr() {
let xhrProto = window.XMLHttpRequest.prototype
while(Object.getPrototypeOf(xhrProto) !== XMLHttpRequestEventTarget.prototype) {
xhrProto = Object.getPrototypeOf(xhrProto);
if (!xhrProto) break;
}
return xhrProto?.constructor
}