Ajax 基础 第二章

Posted codekrist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了 Ajax 基础 第二章相关的知识,希望对你有一定的参考价值。

Ajax 错误处理的几种情况


第一种情况

- 网络畅通,服务器端能接收到请求,服务器端返回的结果不是预期结果

       * 可以判断服务器端返回的状态码 分别进行处理 xhr.status 获取 http 状态码

示 例 :

1- 在 app.js 写入error get请求

app.get('/error', (req, res) => { // 修改状态码 res.status(400).send('not ok')}

2- 创建html文件   07.ajax错误处理.html

<body> <button id="btn"> 发送Ajax请求</button></body></html><script> let btn = document.getElementById('btn'); btn.onclick = function () { let xhr = new XMLHttpRequest();        xhr.open('get', 'http://localhost:3000/error'); xhr.send(); xhr.onload = function () {         consoloe.log(xhr.responseText)        } }</script>

3- 输入网址  http://localhost:3000/07.ajax错误处理.html

4- 获取http状态码

xhr.onload = function () { console.log(xhr.responseText)    console.log(xhr.status) //获取http状态码}

【 Ajax 】基础 第二章

5- 现在就可以对这个状态码进行判断

            如果状态码为 400 打印请求出错

if (xhr.status == 400) { console.log('请求出错') }


【 Ajax 】基础 第二章




第二种情况

- 网络畅通,服务器端没有接收到请求 返回 404 状态码

示 例 :

xhr.open('get', 'http://localhost:3000/error123'); // 在error面写上123 我们并没有这个请求地址


2- 点击发送Ajax请求按钮是404

【 Ajax 】基础 第二章




第三种情况

- 网络畅通 服务器端能接收到请求 服务器端返回 500 状态码

    * 服务器端错误 找后端程序员进行沟通

1- 在app.js中打印 abc

app.get('/error', (req, res) => { console.log(abc)  //修改状态码 res.status(400).send('not ok')})

2- 输入网址  http://localhost:3000/07.ajax错误处理.html

    

【 Ajax 】基础 第二章

第四种情况

-  网络中断 请求无法发送到服务器端

    * 会触发 xhr 对象下面的 onerror 事件 在 onerror 事件处理函数中对错误进行处理

我们怎么才能模拟这种断网的情况呢?下面我们可以根据我所发的图来演示

现在   打开我们的控制台 点击Network

【 Ajax 】基础 第二章


    当断网的情况下是无法触发onload事件的

现在我们来处理断网事件

   //当网断的时候触发onerror事件   xhr.onerror=function(){ console.log('网络中断,无法发送Ajax请求')   }


【 Ajax 】基础 第二章

Ajax状态码 和Http状态码的区别

Ajax状态码 :表示Ajax请求的过程状态 ajax对象返回的

Http状态码 :表示请求的处理结果 是服务器返回的




低版本IE浏览器的缓存问题

 xhr.open('get', 'http:www.codekrist.cn?t='+ Math.random());

示 例 :

1- 在server文件夹中创建一个test文本

【 Ajax 】基础 第二章

现在我们要开始读取文本 要使用 fs模块

let fs = require('fs') //引入fs模块
app.get('/cache', (req, res) => { // 回调函数 fs.readFile('./test.txt', (err, result) => { res.send(result) })}

3- 创建html文件   08.Ajax缓存.html

<body> <button id="btn"> 发送Ajax请求</button></body>
</html><script>let btn = document.getElementById('btn');btn.onclick = function () {   let xhr = new XMLHttpRequest();   xhr.open('get', 'http://localhost:3000/cache');   xhr.send();   xhr.onreadystatechange = function () {      if (xhr.readyState == 4 && xhr.status == 200) {         alert(xhr.responseText)      }   }}</script>

4- 点击按钮

【 Ajax 】基础 第二章

5- 现在我们修改文本 再次点击按钮 依然是我们上一次得到的数据 

现在数据是浏览器缓存中的结果

【 Ajax 】基础 第二章

6- 再次说明  解决办法 

    请求参数 不能使用本该需求的参数名  作为参数名

xhr.open('get', 'http://localhost:3000/cache?t='+Math.random());

现在我们解决了在IE低版本的缓存问题




同步异步概述

你应该知道,javascript 语言是一门“单线程”的语言,不像 java 语言,类继承 Thread 再来个 thread.start 就可以开辟一个线程,所以,javascript 就像一条流水线,仅仅是一条流水线而已,要么加工,要么包装,不能同时进行多个任务和流程。



- 同步

      * 一个人同一时间只能做一件事情, 只有一件事情做完,才能做另一件事情

落实到代码 就是上一行代码执行完成之后 才能执行下一行代码 即代码逐行执行

console.log(1)console.log(2)console.log(3)

- 异步

      * 一个人一件事情做了一半 转而去做其它事情 当其他事情做完后 再回过头继续做之前未完成的事情

落实到代码上 就是异步代码虽然需要花费时间去执行 但程序不会等待异步代码执行完成之后再继续执行后续代码  直接执行后续代码 当后续代码执行完成之后再回头看异步代码是否返回结果 如果已有返回结果 在调用事先准备好的回调函数处理异步代码执行的结果

cosnole.log(1) //1setTimeout(function(){ console.log(2) //3},1000)console.log(3)//2

示 例 :

<script type="text/javascript"> var xhr = new XMLHttpRequest(); console.log(xhr) xhr.open('get', "http://localhost:3000/frist"); xhr.send(); xhr.onload = function () { console.log('2') //后执行 console.log(xhr.responseText) } console.log('1') //先执行</script>





 Ajax 封装

- 问题: 发送一次请求代码过多 发送多次请求冗余且重复

    *  解决方案 :将请求代码封装到函数中 发请求时调用该函数即可

第一种封装方式

1- 下面是我们封装好的Ajax函数发送

function ajax(url, data, method, success) { // 创建异步对象 var xhr = new XMLHttpRequest();    // get 和post 分别写不同的代码    if (method == 'get') { //如果是get    if (data) { //当data中有值 url += '?' + data }    xhr.open(method, url); //设置方法已经url; xhr.send(); //send即可    } else {      xhr.open(method, url); //post请求要设置请求头    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); //判断data发送数据 if (data) {      xhr.send(data) //如果有值就send出去 } else { xhr.send() //如果没有值 直接发送即可      }    }       //注册事件    xhr.onreadystatechange = function () { //在事件中获取数据 并修改页面显示 if (xhr.readyState == 4 && xhr.status == 200) { success(xhr.responseText)     }   } }

2- 调用封装的Ajax函数

    - server文件夹创建的test.txt文本

ajax('/server/test.txt', '', 'get', function (res) {    console.log(res)})


【 Ajax 】基础 第二章




第二种封装方式


封装方法1:提取需要改变部分

我们现在对本次的封装做个详细的概述

1- 创建ajax  以及兼容IE

2-  配置ajax对象

 function ajax() { //1- 创建ajax 以及兼容IE var xhr; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest() } else { xhr = new ActiveXObject('Microsoft.XMLHTTP') } //2- 配置ajax对象 xhr.open()    }

4- 现在开始调用我们的ajax函数 

 ajax({ type: 'get', // 请求方式 url: 'http://localhost:3000/frist', // 请求地址 })

在我们的函数中也应该传递一个 形参 options

options相当于对象的名字  type url ... 

    function ajax(options) { // 定义形参 }

6- 现在 xhr.open() 后面传递的参数就是

 xhr.open(options.type,options.url)

7- 监听xhr对象下面的onload事件    当xhr对象接收完响应数据后触发

 xhr.onload = function () {   console.log(xhr.responseText) }

8- 完整代码

    1-  app.js

【 Ajax 】基础 第二章

    2 - 封装.html

【 Ajax 】基础 第二章

    3 - 控制台打印 

            我们封装的方法可以执行

【 Ajax 】基础 第二章





封装方法2: 提取调用成功函数

在我们的onload事件触发时 调用

在这个函数中调用的是 实参

 xhr.onload = function () { // console.log(xhr.responseText)    options.success(xhr.responseText);    }

在函数中定义一个形参

ajax({ type: 'get', //请求方式    url: 'http://localhost:3000/frist', //请求地址    success:function(data){       console.log('success调用的'+data)    }})

在控制台打印该方法

【 Ajax 】基础 第二章




封装方法2: 定义请求参数  请求方式 请求参数格式类型

1- 请求参数问题

要根据请求方式的不同 把请求参数放入对应的请求方式中

> post 请求 把请求参数放入send方法中

2- 请求参数格式问题

  参数名称=参数值&参数名称=参数值


>  application/x-www-form-urlencoded

     name=codekrist&age=18

>  application/json

    { name:'codekrist',age:19 }

函数的调用者 使用哪种格式方便 ?

    答道 :当然是json更加方便




1- 设置请求参数

示例:

【 Ajax 】基础 第二章

【 Ajax 】基础 第二章

【 Ajax 】基础 第二章

对字符串进行截取& name=codekrist&age=19&

使用  substring( ) 方法

>  是用于提取字符串中介于两个指定下标之间的字符,两个参数,其中第一个参数是必须的,第二个参数是可选的。如果不传第二个参数,默认情况下会提取到最后。返回值是一个新的字符串。准确的说,返回的额字符串包含了第一个参数位置的字符串,而不包含第二个参数位置的元素。

继续将截取后的字符串赋值到 params

 params = params.substring(0, params.length - 1);

【 Ajax 】基础 第二章




2- 判断设置请求方式

if (options.type == 'post') {  //设置post 请求头  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');  xhr.send(params) } else {       xhr.send(); }

1- 设置post请求

【 Ajax 】基础 第二章

2- 控制台显示

【 Ajax 】基础 第二章




封装方法3:判断请求参数格式类型


示例

 ajax({        type: 'post', //请求方式 url: 'http://localhost:3000/frist', //请求地址 data: { name: 'codekrist', age: 19 },        // 请求参数格式 header: { 'Content-Type': 'application/json' },        success: function (data) { console.log('success调用的' + data) } })


 //如果当前请求时post if (options.type == 'post') {         // 设置变量  var ContentType = options.header['Content-Type']; //设置post 请求头 xhr.setRequestHeader('Content-Type', ContentType); //判断用户希望的请求参数格式的类型 if (ContentType == 'application/json') {//如果类型为json //向服务器端传递json数据格式的参数 xhr.send(JSON.stringify(options.data)) } else { // 向服务器端传递普通类型的请求参数 xhr.send(params) } } else { //get 发送请求 xhr.send(); }

控制台打印是否改变了数据格式

【 Ajax 】基础 第二章




封装方法4: 数据请求与成功 回调

完成以上三个封装,我们只知道,获取成功后对该数据进行操作。 但是 当我们失败的时候怎么办呢? 

我们应该使用Http状态码进行判断是否成功获取数据 或 获取数据失败

1- 判断status

xhr.onload = function () {      // console.log(xhr.responseText)      if (xhr.status == 200) { //成功          options.success(xhr.responseText, xhr);      } else { //失败          options.error(xhr.responseText, xhr);      }
 }

2- ajax调用成功失败方法

 ajax({ type: 'post', //请求方式 url: 'http://localhost:3000/frist', //请求地址 data: { name: 'codekrist', age: 19 }, header: { 'Content-Type': 'application/json' }, success: function (data) { console.log('success调用的' + data) }, error: function (data) {            console.log('error调用的' + data) } })

3- app.js 对frist请求 手动设置状态码400

app.post('/frist', (req, res) => { res.status(400).send('Hello CodeKrist')})

【 Ajax 】基础 第二章






> 在使用Ajax请求的时候 服务器端返回的结果大多是json数据作为响应内容

> 但是在客户端呢 我们拿到的是json字符串 所以在使用前我们我们要让json字符串转换为json对象

> 这个操作我们直接封装在函数当中 这样的话我们函数调用者又少关心了一步操作

> 现在的问题是 你怎么确定服务器端获取的就是json数据呢 万一服务器端返回的是一串字符呢 

> 实际上服务器端在返回数据的时候会在响应头设置数据返回类型 我们只要获取到响应头当中设置的数据类     型 然后对类型进行判断就可以了

> 如果服务器端返回的是json类型数据我们在进行转换

> 如果服务器端返回的不是json类型数据我们不再进行转换

现在的问题是我们如何获取响应体的数据呢

在xhr有一个方法就是

// 获取响应头的数据 xhr.getResponseHeader('Content-Type') console.log(xhr.getResponseHeader('Content-Type'))

1- 我们对frist请求得到的是text/html

    app.js中的frist请求方式

app.get('/frist', (req, res) => { res.send('Hello AJAX')})

2- 打印结果 请求数据类型

【 Ajax 】基础 第二章


如果我们换一个json对象格式呢

1- 我们对responseData

        请求得到的是text/html

    app.js中的responseData请求方式

app.get('/responseData', (req, res) => { res.send({ "name": "codekrist" })})


2- 打印结果 请求数据类型

【 Ajax 】基础 第二章


判断返回的是不是application/json类型

includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。

 var contentType=xhr.getResponseHeader('Content-Type') //判断是否包含application/json if(contentType.includes('application/json')){ console.log('包含') }

输出结果

【 Ajax 】基础 第二章

我们将服务器端返回的数据定义变量

 var responseText = xhr.responseText

并返回该数据 监听xhr对象下面的onload事件    当xhr对象接收完响应数据后触发  完整代码

 xhr.onload = function () { //获取响应头的数据 xhr.getResponseHeader('Content-Type') console.log(xhr.getResponseHeader('Content-Type')) var contentType = xhr.getResponseHeader('Content-Type') var responseText = xhr.responseText //服务端返回的数据 //判断是否包含application/json if (contentType.includes('application/json')) { //将json字符串转换为json对象 responseText = JSON.parse(responseText) } // console.log(xhr.responseText) if (xhr.status == 200) { //成功 options.success(responseText); } else { //失败 options.error(responseText); }
}

ajax调用 成功打印数据

 ajax({ type: 'get', //请求方式 url: 'http://localhost:3000/responseData', //请求地址 data: { name: 'codekrist', age: 19 }, header: { 'Content-Type': 'application/json' }, success: function (data) { // console.log('success调用的' + data) console.log(data) }, error: function (data) { console.log('error调用的' + data) } })

输出结果是不是将application/json格式 转换成json对象

【 Ajax 】基础 第二章




> 到目前位置我们的ajax就快要封装好了

> 到现在我们还存在一些问题

> 我们在调用ajax的时候传递了很多的参数

> 如果每次调用ajax函数 都需要传递怎么多的参数也是很不方便的

> 我的想法是这样的  调用ajax参数的时候 传递一些必要的参数就可以了

> 没有传递请求参数的选项 应该有一个默认值 

> 不传递就是用默认值 比如说请求参数的类型

> 如果不传递的话就是用传统的字符串类型的参数

> 如果要使用json数据类型的参数 就传递application/json

这样的需求要如何实现呢

> 我们只需要在函数的内部定义一个对象

> 对象中储存的数据就是默认参数

> 如果用户传递的某个参数就不使用默认值

> 用户哪个参数没传递就用默认值
1- 在ajax函数封装写上这么一段代码

        并将函数内部原本的 options 全部改变成 defaults 

 var defaults = { type: 'get', url: '', data: {}, header: { 'Content-Type': 'application/x-www-form-urlencoded' }, success: function () {}, error: function () {}, }

2- 使用Object.assign方法 

    使用opstions对象中的属性覆盖defaults对象中的属性

如果在调用中没有传递就使用defaults中对象的值

如果在调用中传递就是用options中对象的值

 Object.assign(defaults, options) 

3-现在调用ajax函数

 可以将不必要的实参写入到对象中

 默认请求方式是get请求

  ajax({        url'http://localhost:3000/responseData', //请求地址 success: function (data) { // console.log('success调用的' + data) console.log(data) }
})

4- 在我们responseData请求中 的请求数据格式

app.get('/responseData', (req, res) => { res.send({ "name": "codekrist" })})

5- 控制台输出

6- 如果是post请求呢

在ajax调用时写入post请求方式

 ajax({ type:'post', url: 'http://localhost:3000/responseData', //请求地址
success: function (data) { // console.log('success调用的' + data) console.log(data) }
})

7- 现在请求方式就是post了





最终代码

function ajax(options) { var defaults = { type: 'get',     url'',     data: {},     header: {      'Content-Type''application/x-www-form-urlencoded'      }, success: function () {},        errorfunction ({},      }      //使用opstions对象中的属性覆盖defaults对象中的属性    Object.assign(defaults, options)         //1-  创建ajax  以及兼容IE    var xhr = null;    if (window.XMLHttpRequest) {      xhr = new XMLHttpRequest()    } else {        xhr = new ActiveXObject('Microsoft.XMLHTTP')    }     var params = '';      for (var attr in defaults.data) {         params += attr + '=' + defaults.data[attr] + '&'      }     params = params.substring(0, params.length - 1);       // console.log(params)       //2- 配置ajax对象      xhr.open(defaults.type, defaults.url) //3- 发送请求 //如果当前请求时post     if (options.type == 'post') {         var ContentType = defaults.header['Content-Type'];         //设置post 请求头         xhr.setRequestHeader('Content-Type', ContentType);         //判断用户希望的请求参数格式的类型         if (ContentType == 'application/json') { //如果类型为json          //向服务器端传递json数据格式的参数           xhr.send(JSON.stringify(defaults.data))         } else {          // 向服务器端传递普通类型的请求参数           xhr.send(params)         }       } else {          //get 发送请求          xhr.send();     }
     //4- 监听xhr对象下面的onload事件    当xhr对象接收完响应数据后触发 xhr.onload = function () { //获取响应头的数据 xhr.getResponseHeader('Content-Type') console.log(xhr.getResponseHeader('Content-Type')) var contentType = xhr.getResponseHeader('Content-Type') var responseText = xhr.responseText //服务端返回的数据 //判断是否包含application/json if (contentType.includes('application/json')) { //将json字符串转换为json对象 responseText = JSON.parse(responseText) } // console.log(xhr.responseText) if (xhr.status == 200) { //成功 defaults.success(responseText); } else { //失败 defaults.error(responseText); }
} }
// 调用该方法 ajax({ type:'post', url: 'http://localhost:3000/responseData', //请求地址
success: function (data) { // console.log('success调用的' + data) console.log(data) }
})


以上是关于 Ajax 基础 第二章的主要内容,如果未能解决你的问题,请参考以下文章

AJAX相关JS代码片段和部分浏览器模型

Ajax 基础 第二章

Javascript代码片段在drupal中不起作用

DWR第二篇之逆向Ajax

分享几个实用的代码片段(第二弹)

分享几个实用的代码片段(第二弹)