原生js XMLhttprequest请求onreadystatechange执行两次问题解决

原生js XMLhttprequest请求onreadychange执行两次解决

最近做到一个页面需要兼容IE,然后就写了一个原生 XMLhttprequest请求
直接上错误代码

xmlHttp = new XMLHttpRequest();
        xmlHttp.open("post","https://baidu.com/mianxiang/baidu/biancheng");
        xmlHttp.setRequestHeader("Content-Type","application/json");
        xmlHttp.send(XXXXXXXXXX) ;
        xmlHttp.onreadystatechange = function () {
            if(this.status==200){
                console.log("responseText",this.responseText);
            }
        };

在上面代码中,当status == 200 的console.log内容每次请求,都会在控制台打印两次,也就是说里面的逻辑会被执行两次,百度了很多都没有发现相似问题,和具体解决办法。

xmlHttp = new XMLHttpRequest();
        xmlHttp.open("post","https://baidu.com/mianxiang/baidu/biancheng");
        xmlHttp.setRequestHeader("Content-Type","application/json");
        xmlHttp.send(XXXXXXXXXX) ;
        xmlHttp.onreadystatechange = function () {
            if(xmlHttp.readyState == 4 && this.status==200){
                console.log("responseText",this.responseText);
            }
        };

最后偶然发现了和正确代码的差距,补上“ xmlHttp.readyState == 4 ”
执行一次,问题解决。
分析,可能是因为在没有添加判断readyState时,当options预请求执行时,也会有一次状态码200的,所以会被执行两次,但是疑惑点是预请求不会返回数据,但是在打印时,两次打印都是有数据的。

查资料+请教大佬 = get 知识
知识:

创建xmlhttprequest对象之后没有调用open之前readystate值为0,调用open()之后就变为1了,并且此时onreadystatechange函数与open()几乎是同时执行的。在之后调用send方法之后,在startHttpRequest函数中readystate值仍为1,而调用send方法之后应该有2,3,4三个状态,而只有在startHttpRequest函数用alert语句才可以观察到3个值!这是为什么呢?这是因为在startHttpRequest函数中当解析到send这一句时,并没有真正开始执行send执行。只有send执行,才可以在onreadystatechange函数观察到状态值的变化。readystate不是发送的状态,它是准备发送的状态,要把它想像成“人间大炮一级准备、二级准备、放”这样的口号,不是请求发送本身。同时xmlhttp也不是监听服务器信息,它是在send的时候获取服务器返回的状态信息而已,只有一次,监听则是一直在观察状态。

关于readyState不同状态总结:

(0)未初始化
此阶段确认XMLHttpRequest对象是否创建,并为调用open()方法进行未初始化作好准备。值为0表示对象已经存在,否则浏览器会报错--对象不存在。
(1)载入
此阶段对XMLHttpRequest对象进行初始化,即调用open()方法,根据参数(method,url,true)完成对象状态的设置。并调用send()方法开始向服务端发送请求。值为1表示正在向服务端发送请求。
(2)载入完成
此阶段接收服务器端的响应数据。但获得的还只是服务端响应的原始数据,并不能直接在客户端使用。值为2表示已经接收完全部响应数据。并为下一阶段对数据解析作好准备。
(3)交互
此阶段解析接收到的服务器端响应数据。即根据服务器端响应头部返回的MIME类型把数据转换成能通过responseBody、responseText或responseXML属性存取的格式,为在客户端调用作好准备。状态3表示正在解析数据。
(4)完成
此阶段确认全部数据都已经解析为客户端可用的格式,解析已经完成。值为4表示数据解析完毕,可以通过XMLHttpRequest对象的相应属性取得数据。

这个时候再回顾之前为何执行两次onreadystatechange, 因为当state每次变化的时候都会执行到onreadystatechange , 其实是readyState每次变化都会有执行onreadystatechange ,因为我判断了this.status == 200 ,所以当服务器响应了之后返回了200的状态码,才会执行console.log(),才有上面的执行两次的问题。

至此问题解决,如有不足,望留言指出,补充交流,感谢。

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值