javascript - 当内容显然正确时,如何修复返回代码 0 的 XMLHttpRequest.open()?
问题描述
我正在尝试使用开发人员自动生成的链接调用 API。我正在使用基于https://javascript.info/xmlhttprequest教程的 XMLHttpRequest.open() 方法。但是,当我尝试拨打电话时,我能够达到的唯一状态是“0”,我认为这意味着我的结束(?)。
我尝试了到其他 API 的不同链接,包括那些除了普通链接之外不需要任何东西的链接,并且得到了相同的响应,这意味着它不一定与我想要的 API 和其他解决方案有关(例如$.JSON().done()) 也不合作。
我最小的代码:
<button onclick="getEndDate()">Click Me</button>
<script>
function getEndDate() {
alert("in function");
// create request
var request = new XMLHttpRequest()
alert("request made");
// request data from API (API link automatically generated)
request.open('GET', 'https://holidayapi.com/v1/holidays?key=validkey&country=US&year=2018&pretty', true)
alert("request opened"+ request.status);
// send request (?)
request.send()
alert("request sent");
request.onload = function() {
alert("request loaded");
var data = JSON.parse(this.response)
// If we receive a valid code
if (request.status >= 200 && request.status < 400) {
data.forEach(holiday => {
alert(holiday.name, holiday.date);
})
} else {
alert('error');
}
}
}
</script>
我希望至少能够运行所有警报,但是我只能进入“已发送请求”,这意味着加载请求结果时存在问题。如前所述,在状态中,我期望的是 200 而不是 0。
我是否以完全错误的方式接近这个?如果是这样,我应该以什么方式尝试调用 API?
解决方案
XMLHttpRequest 的send()
方法以某种同步的方式运行。它的部分行为可能是异步的,也可能不是异步的(取决于.open()'s
async 标志),但它的一部分绝对是同步的。
设置事件处理程序(onload
等onreadystatechange
)是同步完成的。这就是 Internet Explorer 实现它的方式,并且自从 Microsoft 发明了 XMLHttpRequest 以来,规范要求它实现它。
具体来说,规范的第 5 步.send()
要求它:
- 如果在关联的 XMLHttpRequestUpload 对象上注册了一个或多个事件侦听器,则设置上传侦听器标志。
所以设置事件监听器是在.send()
函数返回之前完成的,而不是在收到来自网络的响应时。
所以在你的代码中你有:
request.send(); // send will now check if it has .onload registered and
// set up appropriate event listeners.
request.onload = function() { /* ... */ } // too late, this is ignored
您需要在调用之前通过.onload
等.onreadystatechange
或通过设置任何事件侦听器。.addEventListener('load', ...)
.send()
请注意,在XMLHttpRequest 使用的所有官方示例(whatwg 规范、MDN、MSDN 等)中,事件处理程序总是在之前设置,.open()
所以我建议你做同样的事情,即使技术上规范允许你在之后.open()
但之前这样做.send()
:
request.onload = function() { /* ... */ }
request.open('GET', url, true);
request.send();
过去有(我不知道目前是否有)一些浏览器版本允许您在之后设置事件处理程序,.send()
因为它们使用标准 EventEmitters 而不是遵循规范。但是这些实现在技术上并不符合标准,即使感觉是正确的。
推荐阅读
- elasticsearch - 如何加入 elasticsearch 索引进行排序?
- c# - 使用 C# 驱动程序查找 MongoDB 文档并仅匹配数组元素
- powershell - 使用 PowerShell 从 CSV 文件中解密 PGP 并输出到另一个 CSV
- javascript - 如何从JS中的字典数组中获取包含某些子字符串的所有键的数组?
- reactjs - 开玩笑地测试注册表(react App)
- php - Laravel Livewire 线:单击未定义触发功能
- linux-kernel - 加载具有 EXPORT_SYMBOLS 和全局变量的同一个 linux 驱动程序的多个实例
- c# - 查询具有不同包含的基和子类型
- firebase - 颤动一些在 pod 中找不到的包
- r - 闪亮的传单 - 下载地图的范围