#hello,JS:13-01技术方案:Ajax 使用和原理

前端和后端如何交互,从网站的层面上,如何去呈现?如何和后端去交互?如何向后端获取数据和请求?需要一种方法。

一、页面如何和后端交互

几种方法:

1、form表单提交:

form表单提交实例

如我们把method改为get,用get方法拼装成一个带有用户名和密码的新的url地址,向服务器去发送请求,相应关键信息(用户名和密码)都会传递给服务器,进行处理;post则是直接将这些关键信息直接发给服务器(而不是通过url传递),后台监听到数据直接处理。

这里涉及了get和post的处理。请回看:

miya Wang:浅谈HTML表单(一):表单提交原理(涉及post和get)

这种表单提交的交互方式,提交时页面发生跳转即出现新的页面,体验感不好;再者,页面提交为单向提交,后台给什么反馈?反应?均不知道什么结果。

2、websocket

3、ajax

二、Ajax

1、定义:

Ajax,即AsynchronousJavaScript+XML,是一种依赖前端元素获取数据的方法,它是一种技术方案(不是一种新技术),Ajax主要通过XMLHttpRequest这个浏览器的内置对象向服务器发出HTTP请求,并接收HTTP响应,实现在页面不刷新情况下和服务端进行数据交互。

2、交互形式

Ajax一般用xml格式数据进行数据交互,现今ajax与服务器交互则是倾向于JSON格式规范数据格式,后端可以发任何格式的数据格式。

伴随着浏览器(chrome)升级(IE6-10),从原本依赖现有的CSS/HTML/Javascript去向服务器发送请求到现在最核心依赖浏览器提供的XMLHttpRequest对象(使用JS操作这个对象获取相应的响应,得到数据),即

控制台操作XMLHttpRequest、fetch,可显示它们均是浏览器的内置对象


image

三、如何实现Ajax

  • XMLHttpRequest
  • fetch(注意兼容性使用can i use)

实现基本方式:

<script>
        
        var xhr = new XMLHttpRequest()
        xhr.open('GET','/1.json',true)
        xhr.send()
        var data = xhr.responseText
        console.log(data)
</script>

1、通过get方式去请求

(1)通过js去写XMLHttpRequest来设置ajax

//1.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
    var xhr = new XMLHttpRequest()// XMLHttpRequest()是一个函数,通过new的方式去生成一个对象
        xhr.open('GET','/1.json',true)// 做一些设置:发请求,发给谁?/有post或者get方式/同步异步;设置ajax:请求的方法,请求的服务器(或资源),异步方式(true)
        xhr.send()
    </script>
</body>
</html>

控制台显示一个报错:

image

报错显示无法与当前服务器交互,只能通过跨域请求。请求必须以http或者https开头的json格式文件,即所请求的服务器为

'https//1.json'

解决方法:通过http-server服务器去发请求,获取数据

打开该文件的终端,通过终端打开http-server


image

然后输入带有刚才文件名的服务器地址:http://127.0.0.1:8081/1.html 随即出现以下报错,

image

由于还没设置后端数据文件,点开链接出现找不到该网页(404):


image

接下来如何解决:通过模拟数据,创建一个1.json的文件

{
    "name":"wangxiaoqin"
    "age" : 1
}

然后网页打开服务器的json格式地址:http://127.0.0.1:8081/1.json
即出现

image

打开html的服务器网页控制台,看到json数据通过ajax获取到


image

此时,我们拿到数据,并没有在js中操作如何拿到数据,是同步?异步?

第1种:同步的时候,如何拿到数据?
注:此方法为同步,造成网页一直在计算中,不能前进 ,可能造成页面卡死状态
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        var xhr = new XMLHttpRequest()
                xhr.open('GET','/1.json',false) //设置同步
                xhr.send()

                var data = xhr.responseText
                console.log(data)

    </script>
</body>
</html>

此时控制台console响应,数据到来,并通知到如图:


image

总结:

  • 如果是同步的方式执行代码,代码一行行执行,到xhr.send()的时候,代码执行就暂停,漫长地等待着数据的到来,数据到来之后通过 xhr.responseText拿到数据。
  • 设置一个ajax:创建对象——参数设置——发送——数据到来——拿到数据

第2种:异步的方式获取数据
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        var xhr = new XMLHttpRequest()
                xhr.open('GET','/1.json',true)//异步方式
                xhr.send()
        
                xhr.addEventListener('load',function(){
                var data = xhr.responseText
                console.log(data)
               })
      
       // 或者 
       // xhr.onload = function(){
       //     var data = xhr.responseText
      //      console.log(data)
     //     }

    </script>
</body>
</html>

此时控制台console响应,数据到来,并通知到,如图:


image

(2)通过状态码/状态值获取数据
A、添加status(状态码)方式获取【与onload事件相对应】

当我修改代码中json数据文件名:

js中添加一个console.log(xhr.status) (状态码)
范例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>        
        var xhr = new XMLHttpRequest()
                xhr.open('GET','/1a.json',true)//修改json文件名
                xhr.send()
                xhr.addEventListener('load',function(){
                //添加状态码:
            console.log(xhr.status)
            var data = xhr.responseText
            console.log(data)
        })
      
       // 或者 
       // xhr.onload = function(){
       //     var data = xhr.responseText
      //      console.log(data)
       // }

    </script>
</body>
</html>

执行结果如下:将json文件名修改,造成了控制台报错。即明知道出错,但却一无所知


image

不修改json文件名

代码如下:

//1.json
<script>
        var xhr = new XMLHttpRequest()
        xhr.open('GET','/1.json',true)//不修改json文件名
        xhr.send()
        xhr.addEventListener('load',function(){
        console.log(xhr.status)
    var data = xhr.responseText
    console.log(data)
        })
</script>

如图:


image

总结:控制台出现状态码的响应,返回后端设置的相应数据

  • 状态码200,表示这个文件存在;
  • 状态码404,表示这个文件不存在;
  • 状态码503,服务器表示收到请求,但内部自己报错了,未返回合理的数据;
  • 状态码304,表示服务器是进行了缓存状态

当1.json时,

//1.json
<script>        
    var xhr = new XMLHttpRequest()
        xhr.open('GET','/1.json',true)
        xhr.send()
        xhr.addEventListener('load',function(){
        console.log(xhr.status)
       //当状态码为200时,获取这个数据
            if(xhr.status ===200){
                  var data = xhr.responseText
              console.log(data)
            }else{
              console.log('error')
            }        
        })
</script>

结果如图:


image

当1a.json时,

//1a.json
<script>        
    var xhr = new XMLHttpRequest()
        xhr.open('GET','/1a.json',true)
        xhr.send()
        xhr.addEventListener('load',function(){
        console.log(xhr.status)
       //当状态码为200时,获取这个数据
            if(xhr.status ===200){
                    var data = xhr.responseText
                console.log(data)
            }else{
                console.log('error')
            }        
        })
</script>

如图:


image

比较完整地在设置多个状态码条件下,ajax该如何向后台要取数据,完整代码如下

//1.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
   <body>
    <script>        
    var xhr = new XMLHttpRequest()
        xhr.open('GET','/1a.json',true)
        xhr.send()
        xhr.addEventListener('load',function(){
        console.log(xhr.status)
        if((xhr.status >= 200 && xhr.status <300) ||xhr.status ===304){
                var data = xhr.responseText
            console.log(data)
            }else{
            console.log('error')
            }           
        })
        </script>
   </body>
</html>

//数据文件:1.json

{
    "name":"wangxiaoqin"
    "age" : 1
}

B、使用readyState(状态值)方式获取数据【与onreadystatechange事件相对应】
js中添加另一种状态:readyState

绑定事件获取方法:
(1)on+一个事件
(2)addEventListener绑定一个函数事件

范例代码如下:

//1.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>    
    var xhr = new XMLHttpRequest()
        xhr.open('GET','/1.json',true)
        xhr.send()

       // 使用readyStatechange方法
        console.log('readyState:',xhr.readyState)
        xhr.addEventListener('readystatechange',function(){
            console.log('readyState:',xhr.readyState)
        })
       
        // 或者xhr.onreadystatechange = function(){
        //    console.log('readyState:',xhr.readyState)
        // }

        xhr.addEventListener('load',function(){
            console.log(xhr.status)
            if((xhr.status >= 200 && xhr.status <300) ||xhr.status ===304){
                var data = xhr.responseText
                console.log(data)

            }else{
                console.log('error')
            }
            
        })
      
       // // 或者 
       // xhr.onload = function(){
       //      var data = xhr.responseText
          //  console.log(data)
       // }

          xhr.onerror = function(){
            console.log('error')
          }

    </script>
</body>
</html>

控制台如图:


image

对象中有一个状态值:readyState,这个状态与后端交互时,该状态会发生几次改变,每次改变都会触发该状态的change事件,每次监听这个事件,则输出readyState。即第一次请求状态改变为1,当触发change事件的时候,则开始变化:readyState2,3,4

总结:AJAX实际运行中的几种状态值:
AJAX实际运行当中,对于访问XMLHttpRequest(XHR)时并不是一次完成的,而是分别经历了多种状态后取得的结果,对于这种状态在AJAX中共有5种,分别是:
0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了
对于上面的状态,其中“0”状态是在定义后自动具有的状态值,而对于成功访问的状态(得到信息)我们大多数采用“4”进行判断。

2、readyState VS status 区别

通过对readyState 和 status的一系列操作,可以知道:

  • readyState:表明客户端与客户的交互状态过程
  • status:体现的是服务器对请求的反馈,数据是否正常
  • load: 当状态为4(等同于readyState===4),4为一种完成状态(响应内容解析完成状态),触发调用load事件

为此,我专门查了关于eadyState和status两种ajax状态,找到这么一篇资料较为好理解,可以看看,原文戳:
AJAX 状态值(readyState)与状态码(status)详解

(1)AJAX状态值(readyState)与状态码(status)区别
A、AJAX状态值是指,
运行AJAX所经历过的几种状态,无论访问是否成功都将响应的步骤,可以理解成为AJAX运行步骤。如:正在发送,正在响应等,由AJAX对象与服务器交互时所得;使用“ajax.readyState”获得。(由数字1~4单位数字组成)
B、AJAX状态码是指, 无论AJAX访问是否成功,由HTTP协议根据所提交的信息,服务器所返回的HTTP头信息代码,该信息使用“ajax.status”所获得;(由数字1XX,2XX三位数字组成,详细查看RFC)
这就是我们在使用AJAX时为什么采用下面的方式判断所获得的信息是否正确的原因。

if(ajax.readyState == 4 && ajax.status == 200) { 
     putData(ajax.responseText);
}

(2) AJAX运行步骤与状态值说明
在AJAX实际运行当中,对于访问XMLHttpRequest(XHR)时并不是一次完成的,而是分别经历了多种状态后取得的结果,对于这种状态在AJAX中共有5种,分别是:
0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了
对于上面的状态,其中“0”状态是在定义后自动具有的状态值,而对于成功访问的状态(得到信息)我们大多数采用“4”进行判断。

(3)AJAX状态码说明
1:请求收到,继续处理
2
:操作成功收到,分析、接受
3:完成此请求必须进一步处理
4
:请求包含一个错误语法或不能完成
5**:服务器执行一个完全有效请求失败
100——客户必须继续发出请求
101——客户要求服务器根据请求转换HTTP协议版本
200——交易成功
201——提示知道新文件的URL
202——接受和处理、但处理未完成
203——返回信息不确定或不完整
204——请求收到,但返回信息为空
205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件
206——服务器已经完成了部分用户的GET请求
300——请求的资源可在多处得到
301——删除请求数据
302——在其他地址发现了请求数据
303——建议客户访问其他URL或访问方式
304——客户端已经执行了GET,但文件未变化
305——请求的资源必须从服务器指定的地址得到
306——前一版本HTTP中使用的代码,现行版本中不再使用
307——申明请求的资源临时性删除
400——错误请求,如语法错误
401——请求授权失败
402——保留有效ChargeTo头响应
403——请求不允许
404——没有发现文件、查询或URl
405——用户在Request-Line字段定义的方法不允许
406——根据用户发送的Accept拖,请求资源不可访问
407——类似401,用户必须首先在代理服务器上得到授权
408——客户端没有在用户指定的饿时间内完成请求
409——对当前资源状态,请求不能完成
410——服务器上不再有此资源且无进一步的参考地址
411——服务器拒绝用户定义的Content-Length属性请求
412——一个或多个请求头字段在当前请求中错误
413——请求的资源大于服务器允许的大小
414——请求的资源URL长于服务器允许的长度
415——请求资源不支持请求项目格式
416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求也不包含If-Range请求头字段
417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求
500——服务器产生内部错误
501——服务器不支持请求的函数
502——服务器暂时不可用,有时是为了防止发生系统过载
503——服务器过载或暂停维修
504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长
505——服务器不支持或拒绝支请求头中指定的HTTP版本

(4) AJAX运行步骤示义图

image

3、继续探究一下所请求的后端数据文件

在xhr.open()中要求请求服务器,即请求一个资源,而url则是定位一个资源
将所请求的服务器定位成请求一些资源,如'/hello.json'。假如模拟后端的数据,比如请求一个登陆数据:'/login',请求时带有一些参数,如将用户所输入的数据拼装成类似url形式:
'/login?username=wangxiaoqin&password=12345'作为资源请求

4、通过post形式去请求数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
   <body>
    <script>        
    var xhr = new XMLHttpRequest()
        xhr.open('POST','/1.json',true)
        xhr.send('username=wangxiaoqin&password=12345')//直接发送数据
        xhr.addEventListener('load',function(){
            console.log(xhr.status)
            if((xhr.status >= 200 && xhr.status <300) ||xhr.status ===304){
                var data = xhr.responseText
                console.log(data)

            }else{
                console.log('error')
            }           
        })
        </script>
   </body>
</html>

'username=wangxiaoqin&password=12345' 这段拼接的过程可以通过写一个函数展现:

//传递一个参数:
makeUrl({
  username:'wangxiaoqin',
  password:12345
})
//拼接一个url,通过遍历这个对象,进行拼接
function makeUrl(obj){
   var arr = []
   for(var key in obj){
       arr.push(key + '=' + obj[key])
     }
     return  arr.join('&')
   }

那么,xhr.send()便直接可以发送这个对象

xhr.send(makeUrl({
  username:'wangxiaoqin',
  password:12345
}))

四、ajax几种写法

1、第1种:

关键词:

readyState === 4
onreadystatechange

var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://api.jirengu.com/weather.php', true)
xhr.onreadystatechange = function(){
    if(xhr.readyState === 4) {
        if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            //成功了
            console.log(xhr.responseText)
        } else {
            console.log('服务器异常')
        }
    }
}
xhr.onerror = function(){
    console.log('服务器异常')
}
xhr.send()

2、第2种:

关键词:
onload

var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://api.jirengu.com/weather.php', true)
xhr.onload = function(){
    if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
        //成功了
        console.log(xhr.responseText)
    } else {
        console.log('服务器异常')
    }
}
xhr.onerror = function(){
    console.log('服务器异常')
}
xhr.send()

3、第3种:封装1个ajax

//封装,调用ajax对象,传递一些固定参数
function ajax(opts){
    var url = opts.url
    var type = opts.type || 'GET'// ||或:前者undefined,默认后者
    var dataType = opts.dataType || 'json'
    var onsuccess = opts.onsuccess || function(){}
    var onerror = opts.onerror || function(){}
    var data = opts.data || {}
    
    //将上面用户请求的数据对象进行处理,拼接一个url
    var dataStr = []
    for(var key in data){
        dataStr.push(key + '=' + data[key])
    }
    dataStr = dataStr.join('&')
    
    if(type === 'GET'){
        url += '?' + dataStr
    }
   
   //做一个ajax
    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))//返回的数据
            }else{
                onsuccess( xhr.responseText)
            }
        } else {
            onerror()
        }
    }
    xhr.onerror = onerror
    if(type === 'POST'){
        xhr.send(dataStr)
    }else{
        xhr.send()
    }
}

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

推荐阅读更多精彩内容