使用全局XMLHttpRequest是否为不良实践?代码无响应问题求助
问题1:避免全局XMLHttpRequest变量的优化方案
你当前依赖全局XHR变量的核心原因是HandlePing函数需要访问pingSite内创建的XHR实例,解决思路是让处理函数直接访问局部XHR变量,无需暴露到全局,推荐两种实用方案:
方案1:闭包方式(将处理函数定义在pingSite内部)
利用JavaScript闭包特性,让内部函数直接读取外部函数的局部变量,代码示例:
function pingSite() { const xhr = new XMLHttpRequest(); let response = 'xyz'; if (!xhr) { response = 'Internal error: Cannot create XMLHTTP instance.'; return response; } // 直接在内部定义状态处理函数,无需全局变量 xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE) { try { if (xhr.status === 200) { alert("Server is up"); } else { alert(`Request failed: ${xhr.status} ${xhr.statusText}`); } } catch (error) { alert(`Caught Exception: ${error.description || error.message}`); } } else { response = 'Pinging...'; } }; // 必须添加完整协议前缀,否则会被当作相对路径 xhr.open('GET', 'https://mysite.com'); xhr.send(); return response; }
方案2:使用onload/onerror事件替代onreadystatechange
XMLHttpRequest提供了更简洁的专用事件:onload(请求完成时触发)和onerror(网络错误时触发),同样可以在pingSite内部定义,避免全局依赖:
function pingSite() { const xhr = new XMLHttpRequest(); let response = 'xyz'; if (!xhr) { response = 'Internal error: Cannot create XMLHTTP instance.'; return response; } xhr.onload = function() { if (xhr.status === 200) { alert("Server is up"); } else { alert(`Request failed: ${xhr.status} ${xhr.statusText}`); } }; xhr.onerror = function() { alert("Network error occurred, server may be unreachable"); }; xhr.open('GET', 'https://mysite.com'); xhr.send(); return response; }
另外注意:你代码中的response变量未声明,会自动成为全局变量,这也是不良实践,必须添加let/const声明为局部变量。
问题2:无任何提示的可能原因及解决
你的代码没有弹出提示,大概率是以下几个问题导致:
URL路径错误
你写的mysite.com缺少协议前缀(http://或https://),浏览器会将其当作当前页面的相对路径(比如当前页面是http://localhost:8080,实际会请求http://localhost:8080/mysite.com),导致请求地址无效。必须使用完整的URL:https://mysite.com。跨域请求被拦截
如果当前页面域名与mysite.com不同,浏览器会触发CORS(跨域资源共享)限制,请求被拦截。此时需要目标服务器配置CORS响应头,或改用同域名下的接口进行检测。事件监听逻辑缺陷
原代码中HandlePing依赖全局XHR变量,去掉全局变量后,函数内部的xhr会指向未定义的变量,导致逻辑无法执行。使用上面闭包或事件绑定的方案可解决该问题。异常捕获不兼容
原代码catch块仅读取error.description,但标准Error对象的错误信息在error.message属性中,仅IE浏览器使用description,改成error.description || error.message可兼容更多场景。
内容的提问来源于stack exchange,提问作者SomeKindaHooty

