Fork me on GitHub

# ajax入门(1)

ajax入门(1)

简单了解xmlHttpRequest

​ 网上资料很多,这里举一点基础的。

​ 看这个

https://segmentfault.com/a/1190000004322487 学习了一定时间后发现的一个很详细的,下面也是部分转载这个文章

​ 之后可以学 fetch APIhttps://www.w3ctech.com/topic/854 先给自己挖坑

http 请求

​ http 请求头有四种类型,分别为

  • 通用头部

  • 请求头部

  • 响应头部

  • 内容头部 content-type

    内容头部

     xmlhttp.open("POST", "/searchMeg", true);
    
            // xmlhttp.open("GET", "/test_war_exploded/searchMeg", true);
            xmlhttp.setRequestHeader("Content-type",
                    "application/x-www-form-urlencoded");
            xmlhttp.send("name" + name);
    

    content-type 的取值是告诉服务端,你传递过去的内容是啥,你应该准备好如何接受,

    取值分析

    ​ 常用:’application/json’, ’application/x-www-form-urlencoded’,’ multipart/form-data’

    • ajax 默认类型 :application/x-www-form-urlencoded

      这时前段可以以对象方式直接给后端,或者以json方式传给后端,当action为get时候,浏览器用x-wwww-form-urlencoded 的编码方式 把 form 数据转换成一个字串 (name1=value&name2=value2),然后把这个字串append到url后面,用?分割,加载这个新的url,当action为post的时候,浏览器吧form数据封装到http body 中,然后发送到server ,在浏览器控制台可以看到他们都是以 from data 的形式展现。

ajax 通常会发送get、post 两种请求

  • get 请求时,send 只能传递null 作为参数,因为send()方法是将数据作为请求体发送,而get方法没有请求体。所以send中填了数据也无效。

  • 要通过过get请求向后台传输数据 只能在 url 的末尾追加查询字符串 ? & 链接

  • post请求,可以在url后,同时post方法可以利用send()方法来传递请求体数据给后台,通过send()发送的数据也要经过encodeURIComponent方法的处理。不同的是post方法在发送请求前必须先使用setRequestHeader("Content-Type","application/x-www-form-urlencoded")方法来设置表单内容类型,这样数据才会正常的被后台收集到,否则就会出现在"rawPostData"数据中(不同编程语言不同)。

    代码源于github上不知道哪个老哥的。冒犯一下。

     //ajax异步处理提示数据
        function sreach() {
          document.getElementById("asd").innerHTML="asdasdasd";
          var name = document.getElementById("search").value;
          if (name == "" || name==null) {
            removeCode();
    
          } else {
            var xmlhttp;
            if (window.XMLHttpRequest) {
              // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
              xmlhttp = new XMLHttpRequest();
            } else {
              // IE6, IE5 浏览器执行代码
              xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function() {
              if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
    
                /*
                 * document.getElementById("myDiv").innerHTML =
                 * xmlhttp.responseText;
                 */
                var result = xmlhttp.responseText;
                document.getElementById("asd").innerHTML=result;
                // var json = eval("(" + result + ")");
                // addNode(json);
              }
            }
            xmlhttp.open("POST", "/searchMeg", true);
    
            // xmlhttp.open("GET", "/test_war_exploded/searchMeg", true);
            xmlhttp.setRequestHeader("Content-type",
                    "application/x-www-form-urlencoded");
            xmlhttp.send("name=" + name);
          }
    

后端回传

常用

response.getWriter().write()

  • response.getWriter().writer(),只能打印输出文本格式的(包括html标签),不可以打印对象
    客户端演示代码

response.getWriter().print()

  • response.getWriter().print(),不仅可以打印输出文本格式的(包括html标签),还可以将一个对象以默认的编码方式转换为二进制字节输出

​ 挖坑

​ 我在idea 上怎么都跑不通这一段。即使加了对应的包(没有缺任何一个。而且网上基本以eclipse….我找不出来原因。)

//		response.getWriter().println(""JSONArray.fromObject(list).toString());

这个 markdown 为什么会变成这样啊...
我之前写的$$ $$ 也不支持。。大家可以去我上面贴的第一个人那里去看

事件触发条件

下面是我自己整理的一张xhr相关事件触发条件表,其中最需要注意的是 onerror 事件的触发条件。

事件 触发条件
onreadystatechange 每当xhr.readyState改变时触发;但xhr.readyState由非0值变为0时不触发。
onloadstart 调用xhr.send()方法后立即触发,若xhr.send()未被调用则不会触发此事件。
onprogress xhr.upload.onprogress在上传阶段(即xhr.send()之后,xhr.readystate=2之前)触发,每50ms触发一次;xhr.onprogress在下载阶段(即xhr.readystate=3时)触发,每50ms触发一次。
onload 当请求成功完成时触发,此时xhr.readystate=4
onloadend 当请求结束(包括请求成功和请求失败)时触发
onabort 当调用xhr.abort()后触发
ontimeout xhr.timeout不等于0,由请求开始即onloadstart开始算起,当到达xhr.timeout所设置时间请求还未结束即onloadend,则触发此事件。
onerror 在请求过程中,若发生Network error则会触发此事件(若发生Network error时,上传还没有结束,则会先触发xhr.upload.onerror,再触发xhr.onerror;若发生Network error时,上传已经结束,则只会触发xhr.onerror)。注意,只有发生了网络层级别的异常才会触发此事件,对于应用层级别的异常,如响应返回的xhr.statusCode4xx时,并不属于Network error,所以不会触发onerror事件,而是会触发onload事件。

事件触发顺序

当请求一切正常时,相关的事件触发顺序如下:

  1. 触发xhr.onreadystatechange(之后每次readyState变化时,都会触发一次)
  2. 触发xhr.onloadstart
    //上传阶段开始:
  3. 触发xhr.upload.onloadstart
  4. 触发xhr.upload.onprogress
  5. 触发xhr.upload.onload
  6. 触发xhr.upload.onloadend
    //上传结束,下载阶段开始:
  7. 触发xhr.onprogress
  8. 触发xhr.onload
  9. 触发xhr.onloadend

发生abort/timeout/error异常的处理

在请求的过程中,有可能发生 abort/timeout/error这3种异常。那么一旦发生这些异常,xhr后续会进行哪些处理呢?后续处理如下:

  1. 一旦发生aborttimeouterror异常,先立即中止当前请求
  2. readystate 置为4,并触发 xhr.onreadystatechange事件
  3. 如果上传阶段还没有结束,则依次触发以下事件:
    • xhr.upload.onprogress
    • xhr.upload.[onabort或ontimeout或onerror]
    • xhr.upload.onloadend
  4. 触发 xhr.onprogress事件
  5. 触发 xhr.[onabort或ontimeout或onerror]事件
  6. 触发xhr.onloadend 事件

在哪个xhr事件中注册成功回调?

从上面介绍的事件中,可以知道若xhr请求成功,就会触发xhr.onreadystatechangexhr.onload两个事件。 那么我们到底要将成功回调注册在哪个事件中呢?我倾向于 xhr.onload事件,因为xhr.onreadystatechange是每次xhr.readyState变化时都会触发,而不是xhr.readyState=4时才触发。

xhr.onload = function () {
    //如果请求成功
    if(xhr.status == 200){
      //do successCallback
    }
  }

上面的示例代码是很常见的写法:先判断http状态码是否是200,如果是,则认为请求是成功的,接着执行成功回调。这样的判断是有坑儿的,比如当返回的http状态码不是200,而是201时,请求虽然也是成功的,但并没有执行成功回调逻辑。所以更靠谱的判断方法应该是:当http状态码为2xx304时才认为成功。

  xhr.onload = function () {
    //如果请求成功
    if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
      //do successCallback
    }
  }
posted @ 2019-07-10 14:32  EsMussSeinHui  阅读(227)  评论(0编辑  收藏  举报