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(){
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容