ajax

前端与后端的交互

  • 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(){
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容