ajax

作者: 流着万条永远的河 | 来源:发表于2017-09-19 00:16 被阅读0次

    前端与后端的交互

    • form表单提交,最原始的方法,登录框之类,input的name+value,submit提交到form的action地址上.post/get的方式提交。
      举例:
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <body>
    <form action="/form.html" method="get">
      <input type="text" name="username" placeholder="username">
      <input type="password" name="password" placeholder="password">
      <input type="submit">
    </form>
    </body>
    </html>
    
    如图:
    随便输入,提交看看:
    看看提交后跳转的页面的URL,域名加action的内容?输入的内容的组合。换句话说,浏览器构造了这个新的URL发给服务器请求。对应的关键信息服务器也收到了,服务器就会处理了。
    get是把输入信息拼装成URL发过去,post是把信息直接发送到后台。

    这是前端把数据给了后台。这方式很老,缺点是发送时候会跳转,就算不跳转,当前页面也会刷新,这体验就差了。还有,这是单向的,只提交后台了,后台什么响应?不知道,反正页面跳了。到底成功了?
    有木有方法,可以不跳转页面,不刷新,直接发请求,收数据,并知道进程?所以ajax了。

    • ajax是什么?
      它是一种技术方案,就是为了解决一些问题提出的方法。它依赖现有的css/HTML/JS,算是依赖这种环境,在这个平台上实现的,最核心的依赖是浏览器提供的XMLHttpRequest对象,是这个对象使浏览器发出HTTP请求与接收HTTP响应的。实现页面不刷新的情况下和服务端交互数据。
      刚开始是XML格式的数据,后来倾向于JSON格式,理论上任何格式都可以。
      用JS操作XMLHttpRequest这个对象向服务器发请求,这个对象就可以得到数据了。
      后来浏览器升级了,又出现了一种方案叫frtch,也可以搞定,但是比较新,所以兼容性差。所以,它也可以说是ajax的子集里。
      例子来:
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <body>
    <script>
      var xhr = new XMLHttpRequest()    //创建对象,XMLHttpRequest()是个函数。
    //就可以在这个对象上操作,这对象可以干嘛?可以做设置,比如要发请求,发给谁,是get还是post,是同步还是异步?
    //同步就是我发了请求,处于等待中卡死了,后端给我响应后,才会执行后面的代码。
    //异步就是发了请求就不管了,做个事件监听的类似,内部状态改变了满足我的条件了,监听到了再做。setTimeout也是异步的,时间点到了,才执行。
    xhr.open('GET','/hello.json',true)   
    //这是设置的方法,三个参数,请求类型是get还是post;请求地址(这里服务器先不管);异步是true.
    //到了这里,还没有发,什么时候发?现在就可以:
    xhr.send()
      //这时候打开页面,再进入控制台,有报错,说域名是file开头,必须以http(s)开头才可,我这里在JS.bin上或者在终端的http-server上都可的。
      </script>
    </body>
    </html>
    

    在终端的静态服务器上打开控制台的Network,刷新页面,如图


    有了请求的内容。
    再看反馈
    没有找到?原本写法是向hello.json里获取请求,也就是向图片中的http://192.168.1.106:8080/hello.json去获取,而这个 http://192.168.1.106:8080/hello.json 是不是存在?直接打开这个网页:
    木有啊。这时候怎么办?我可以在这个路径上新建一个:
    在符合这个路径上建了个文件hello.json:
    {
        "name":"haha",
         "age":3 
    }
    

    再打开 http://192.168.1.106:8080/hello.json ,如图


    再刷新下http://192.168.1.106:8080/wo.html,看看还有木有报错,如图

    现在又有问题了,到了之后,代码里并没有说怎么办啊,我如何去拿到数据?

    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello.json',false)   //同步的
      xhr.send()
      var date = xhr.responseText          //文本内容
      console.log(date)             //显示出来
      </script>
    
    如图

    最主线的流就是,创建对象,注明请求的设置,再发送,发送了,就接收后端的数据,再针对数据进行后续设置操作。
    当然,不想同步等着后台数据的到来,很多ajax都卡住了,太慢了。需要异步的方式:

    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello.json',true)
      xhr.send()
    //可是这时候直接执行下一行,后台还没有反馈回来呢,只能是undefined了,等数据来了,代码都执行完了。
      var date = xhr.responseText
      console.log(date)
      </script>
    
    如图

    啥都没有。这时候需要干嘛?需要监听:

    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello.json',true)
      xhr.send()
      xhr.onload = function(){
        var date = xhr.responseText
        console.log(date)
      }  
     </script>
    //也可以xhr.addEventListener('load',function(){
          var date=xhr.responseText
            console.log(date)
    })
    
    如图

    发了请求后就不管了,走侦听事件的流程。
    一般都是用异步的。

    再往细节去控制这个交互过程

    • 明明有报错,可是一无所知
    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello1.json',true)    //请求hello1.json这个不存在的文件
      xhr.send()
      xhr.onload = function(){
        var date = xhr.responseText
        console.log(date)
      }
    </script>
    
    如图

    有报错,但是我却不知道。

    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello1.json',true)
      xhr.send()
      xhr.onload = function(){
        console.log(xhr.status)              //
        var date = xhr.responseText
        console.log(date)
      }
    </script>
    
    如图

    输出了404。

    把hello1.json改回hello.json,再运行:
    输出200.
    如果status是404,就是错,是200,就正常。

    status是交互数据的进程的属性,所以,这时候可以做个判断了:

    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello.json',true)
      xhr.send()
      xhr.onload = function(){
        console.log(xhr.status)
        if(xhr.status ===200){
          var date = xhr.responseText
          console.log(date)
        }else{
              return 'error'
    }
      }
    </script>
    
    如图
    再改成hello1.json,如图
    出现了404.

    但是,status不能都是200,它还有其他值的。它一般是200到300里的数表示不同状态。

    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello1.json',true)
      xhr.send()
      xhr.onload = function(){
        console.log(xhr.status)       //304是走缓存的,重定向
        if((xhr.status >=200 && xhr.status<300) ||xhr.status===304){
          var date = xhr.responseText
          console.log(date)
        }else{
          console.log('error') 
        }
      }
    </script>
    
    • 其他用法
      服务器根本没接收到请求:
    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello1.json',true)
      xhr.send()
      xhr.onload = function(){
        console.log(xhr.status)
        if((xhr.status >=200 && xhr.status<300 )||xhr.status===304){
          var date = xhr.responseText
          console.log(date)
        }else{
          console.log('error') 
        }
      }
      xhr.onerror =function(){
        console.log('error')
      }            //断网了,根本没到服务器的时候,可以测试下的。
    </script>
    
    • xhr.ontimeout = function(){
      }超时了,比如设定时间5秒,超过了时间,请求还没到,就可以执行什么什么了。
    • 再研究下onload
      什么情况下叫load?
      这时候需要看这个属性:xhr.onreadystatechange = function(){
      },同样可写成xhr.addEventListener('readystatechange',function(){})
    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello.json',true)
      xhr.send()
      xhr.addEventListener('readystatechange',function(){
        console.log('readyState:',xhr.readyState)
      })
      xhr.onload = function(){
        console.log(xhr.status)
        if((xhr.status >=200 && xhr.status<300 )||xhr.status===304){
          var date = xhr.responseText
          console.log(date)
        }else{
          console.log('error') 
        }
      }
      xhr.onerror =function(){
        console.log('error')
      }
    </script>
    
    运行下,如图

    这是什么意思呢?我们对象里有个状态叫readyState,在交互时候,前端跟后端有几个握手的过程,我发请求了,你发了啊,我看看,看了吗,看了,可以发数据了吗,可以,什么时候,马上,,,
    每一次握手,这个状态就改变了,这个事件叫readystatechange事件,表现成readyState的值。

    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('GET','/hello.json',true)
      xhr.send()
      console.log('readyState:',xhr.readyState)
      xhr.addEventListener('readystatechange',function(){
        console.log('readyState:',xhr.readyState)
      })
      xhr.onload = function(){
        console.log(xhr.status)
        if((xhr.status >=200 && xhr.status<300 )||xhr.status===304){
          var date = xhr.responseText
          console.log(date)
        }else{
          console.log('error') 
        }
      }
      xhr.onerror =function(){
        console.log('error')
      }
    </script>
    
    如图

    到4就结束,接着返回200的状态码,所以,有时候,有些这种写法:

    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4 && xhr.status === 200 ){
              console.log(xhr.responseText)
    }
    }
    

    原理是类似的。

    把hello.json改成hello1.json运行下,如图
    • 说明,只要服务器收到请求,就会有readystatechange这个属性,除非断网,只是交互的状态而已。
      status才是对数据的正常与否的管理。
      而load是状态变成4时,就自动触发load。

    走个流程看看

    var xhr = new XMLHttpRequest()
    xhr.open(type,URL,异步同步)
    xhr.send()
    xhr.ontimeout=function(){
          console.log('请求超时')
    }
    //发送
    xhr.ontimeout=function(){
          console.log('请求超时')
    }        //请求数据没收到超时处理
    xhr.readyState     //交互过程从1到4的值
    xhr.status             //浏览器收到后端对发的请求的对错的判断
    xhr.onload()      //对收到数据的处理
    xhr.onerror          //后端没有收到请求的处理
    

    请求的是路由

    我们上面写的第二个参数是请求的地址嘛,不要把/helo.json当成文件,这是特殊例子,在静态服务器上搞的。如何理解这个参数呢?
    我们请求的是一个资源,URL定位一个资源资源的名字是/helo.json。
    现在我想要资源,名字叫/hello/world。这时候,需要模拟后端,接收请求。另外,请求时,会有参数,比如/login,向登录地址发请求,我们需要传递些参数的,就变成这样的结果:
    '/login?username=haha&password=123'
    数据拼装成URL格式了,发请求。这是对于get形式的。

    post的呢?

    <script>
      var xhr = new XMLHttpRequest()
      xhr.open('POST','/login',true)        //这里不是'/login?username=haha&password=123'了
      xhr.send('username=haha&password=123')           //放到send这里,字符串哦。
      console.log('readyState:',xhr.readyState)
      xhr.addEventListener('readystatechange',function(){
        console.log('readyState:',xhr.readyState)
      })
      xhr.onload = function(){
        console.log(xhr.status)
        if((xhr.status >=200 && xhr.status<300 )||xhr.status===304){
          var date = xhr.responseText
          console.log(date)
        }else{
          console.log('error') 
        }
      }
      xhr.onerror =function(){
        console.log('error')
      }
    </script>
    

    对应的出个函数把拼装name&password直接做出来:

     mkURL({
        username:'haha',
        age:3
      })              //数据是key,value的值,所以参数必须是对象。
    function mkURL(obj){
          var arr=[]
          for(var key in obj){
            arr.push(key + '=' +obj[key])
          }                       //结果是要拼接,拼接了两层,各自的key,value,=拼,最后所得用&连接。
    //所以需要先遍历。然后,先完成最内层拼接,最后用数组的join把各项连接。
          return arr.join('&')
      }
    //这时候,xhr.send()的参数就是mkURL(obj)了。
    

    封装的ajax

    
    function ajax(opts){
        var url = opts.url                         //参数中的URL
        var type = opts.type || 'GET'                 //方式,默认是'GET'    var dataType = opts.dataType || 'json'          //返回数据类型,默认是json格式
        var onsuccess = opts.onsuccess || function(){}     //如果用户传递了,就用用户的,否则,,,
        var onerror = opts.onerror || function(){}            //如果用户传递了,用用户的,否则,,,
        var data = opts.data || {}                      //如果用户传递了,用用户的,否则为空数据。
    
    
        var dataStr = []
        for(var key in data){
            dataStr.push(key + '=' + data[key])
        }
        dataStr = dataStr.join('&')  
    //类似上面的那个,就是处理用户的数据     
    
        if(type === 'GET'){
            url += '?' + dataStr
        }       //get格式的信息处理
    
        var xhr = new XMLHttpRequest()
        xhr.open(type, url, true)
        xhr.onload = function(){
            if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
                //成功了
              if(dataType === 'json'){
                    onsuccess( JSON.parse(xhr.responseText))         //收到的数据都是字符串格式,如果约定的是JSON格式,那发的就是JSON格式的字符串,再转回成onsuccess对象。
                }else{
                    onsuccess( xhr.responseText)
                }
            } else {
                onerror()             //否则执行onerror()
            }
        }
        xhr.onerror = onerror             //  掉网了执行onerror()
       //对send()的设置,是post,就有参数,否则没有参数。
     if(type === 'POST'){
            xhr.send(dataStr)
        }else{
            xhr.send()
        }
    }
    
    //大纲是这个:调用ajax,就传递一个对象,对象里需要有url,type,等。
    ajax({
        url: 'http://api.jirengu.com/weather.php',
        data: {
            city: '北京'
        },
        onsuccess: function(ret){
            console.log(ret)
        },
        onerror: function(){
            console.log('服务器异常')
        }
    })
    

    封装好了的皮:

    ajax({
        url: 'http://api.jirengu.com/weather.php',
      type:'post',
    dateType:'text',
        data: {
            city: '北京'
        },
        onsuccess: function(ret){
            console.log(ret)
            render(ret)
        },
        onerror: function(){
            console.log('服务器异常')
            showError()
        }
    })
    function render(json){
    }              //把数据拼装成DOM放到页面上
    function showError(){
    }
    

    相关文章

      网友评论

          本文标题:ajax

          本文链接:https://www.haomeiwen.com/subject/wjwbsxtx.html