AJAX

  1. JS 是一门语言,JSON 是另一门语言,JSON 这门语言抄袭了 JS这门语言
  2. AJAX 就是用 JS 发请求
  3. 响应的第四部分是字符串,可以用 JSON 语法表示一个对象,也可以用 JSON 语法表示一个数组,还可以用 XML 语法,还可以用 HTML 语法,还可以用 CSS 语法,还可以用 JS 语法,还可以用我自创的语法

背景


  • AJAX是浏览器上的功能
    • 浏览器可以发请求,收响应,那么可以将这个功能暴露给JS吗?
    • 于是浏览器在windows上加一个XMLHttpRequest函数
    • 用这个构造函数(类)可以构造出一个对象
    • JS通过它实现发请求,收响应
  • AJAX诞生
    • 最先由微软的IE5推出来的
    • 后来Firefox和Opera才跟进的

如何发请求?


  1. 用 form 可以发请求,但是会刷新页面或新开页面

    • image.png
    • get请求是可以携带参数的,想看response,点击一下view sourse就可以看到
    • image.png
    • POST请求 是不带参数的请求。第四部分是发送的参数数据
    • image.png
  2. 用 a 可以发 get 请求,但是也会刷新页面或新开页面

    • image.png
    • a标签会在当前页面刷新或者新开页面刷新,不是很好用
  3. 用 img 可以发 get 请求,但是只能以图片的形式展示

  4. 用 link 可以发 get 请求,但是只能以 CSS、favicon 的形式展示

  5. 用 script 可以发 get 请求,但是只能以脚本的形式运行

有没有什么方式可以实现

  1. get、post、put、delete 请求都行
  2. 想以什么形式展示就以什么形式展示

微软的突破


IE 5 率先在 JS 中引入 ActiveX 对象(API),使得 JS 可以直接发起 HTTP 请求。
随后 Mozilla、 Safari、 Opera 也跟进(抄袭)了,取名 XMLHttpRequest,并被纳入 W3C 规范

XMLHttpRequest就是全局下面的一个全局对象
之前出过一个gmail,用来收发邮件,当邮件被点击的时候就会局部更新展示出来。这个突破是可以在网页上面收发邮件,而不用在软件上面。

整个市场因为ActiveX以及XMLHttpRequest的出现,而发生了很大的变化

AJAX


Jesse James Garrett 将如下技术取名叫做 AJAX(Async Javascript And XML):异步的 JavaScript 和 XML

  1. 用 XMLHttpRequest 发请求
  2. 服务器返回 XML 格式的字符串(后来不用XML,用了JSON)
  3. JS 解析 XML,并更新局部页面

如何使用 XMLHttpRequest


  1. 我们复习一下前面写的server,server的response总是字符串,我们可以给它一个页面格式的字符串,这样到浏览器中就可以解析成网页了,代码如下
    var http = require('http')
    var fs = require('fs')
    var url = require('url')
    var port = process.argv[2]
    if(!port){
        console.log('请指定端口奥好不好?\nnode server.js 8888 这样不会吗?')
        process.exit(1)
    }
    var server = http.createServer(function(request, response){
        var parsedUrl = url.parse(request.url, true)
        var pathWithQuery = request.url
        var queryString = ''
        if(pathWithQuery.indexOf('?') >= 0){queryString=pathWithQuery.substring(pathWithQuery.indexOf('?'))}
        var path = parsedUrl.pathname
        var query = parsedUrl.query
        var method = request.method
        /*********从这里开始看,上面不要看*********/
        console.log('方方说:含查询字符串的路径为\n' + pathWithQuery)
    
        if(path === '/'){
            let string = fs.readFileSync('./index.html')  //同步读取网页文件
            response.statusCode = 200
            response.setHeader('Content-Type', 'text/html;charset=utf-8')
            response.write(string)    // 将网页文件写入到response中返回
            response.end()
        }else{
            response.statusCode = 404
            response.setHeader('Content-Type', 'text/html;charset=utf-8')
            response.write('呜呜呜')
            response.end()
        }
        /*********代码结束,下面不要看*********/
    })
    server.listen(port)
    console.log('监听 ' + port + ' 成功\n请在空中转体720度然后用电饭煲打开 http://localhost:' + port)
    
  2. 服务器返回的不是html,而是符合html语法的字符串;
  3. HTTP的访问路径都是绝对路径,前面没有点的。这个路径需要与HTTP请求头第一句里面的路径一样,否则会请求失败
  4. 我们网页中如果有要访问的资源,也要将对应到地址信息放入服务器中,否则会请求失败的。


    image.png

    image.png
  5. 接下来我们看看ajax怎么写。
  6. open适用于配置的,不是发请求的。第一个参数是请求方式,第二个参数是请求地址,后面三个参数一般默认,其中第三个参数是是否异步,一定要异步,不然就不是AJAX


    image.png
  7. 我们写一个简单的AJAX用于监听按钮点击事件,这里我们不使用link标签加载css,而是用ajax
    • 四个步骤
      • 创建XMLHttpRequest对象
      • 调用对象的open方法
      • 监听对象的onload&onerror事件
        • --专业前端会改用onreadystatechange事件
        • --在事件处理函数中操作具体的文件
      • 调用对象的send方法(发送请求)
    // 使用ajax请求CSS内容
    myButton.addEventListener('click', (e)=>{
        let request = new XMLHttpRequest()    // 创建一个请求对象
        request.open('GET', '/xxxx')    // 配置参数
        request.onload = () => {
            console.log('成功了')
            
            // 创建 style 标签
            const style = document.createElement('style')
            // 填写style内容
            style.innerHTML = request.response
            // 插到页面中
            document.head.appendChild(style)
        }
        request.onerror = () => {
            console.log('失败了')
        }
        request.send()    // 发送请求
    })
    
  8. 这样点击按钮的时候,可以发送请求,请求的方式可以是get,post,put,delete甚至可以自己写一个请求方法,这样我们就实现了使用 XMLHttpRequest 发请求。


    image.png
  9. 我们现在实现以下服务器返回XML(虽然现在不用XML了),我们可以查询xml mime type查询XML请求头中Content-Type需要写成什么样。
    image.png
  10. 我们接下来实现的是,让JS阅读这段返回的XML,我们之前创建的请求是有监听事件的

    [
    image.png
  11. 我们看到里面有一个readyState,这个其实监听的是状态。我们拿到这个readyState之后,发现是1,但是XMLHttpRequest里面的却是4。这是因为这个请求需要时间的,这儿的33ms已经是很长了。一个赋值时间很短的


    image.png

    image.png
  12. 请求的时间太长了,所以一时拿不到状态的,我们可以更改一下代码,让状态跟踪不断进行,这样就发现,可以找到状态了


    image.png

    image.png
  13. 这个readState的意思


    image.png
  14. 第三行。响应可能是分次返回的,但是这种分次我们无法获知,假设我们返回的有100M,是不可能一次性返回的。
  15. 我们上面的响应不是从1直接到4的,而是2和3实在太慢了
  16. 0,1,2,3,4是依次经过的。我们需要记忆的是4状态,说明请求已经将响应下载完毕了
  17. 有没有一种办法监控到各个状态呢?onreadystatechange
    • 创建req对应的readystate为0
    • 使用open对应的是1
    • 使用send对应的是2
    • 当资源开始下载的时候,状态为3
    • 当资源完成下载的时候,状态为4
    • image.png
    myButton.addEventListener('click', (e)=>{
        let request = new XMLHttpRequest()    // 创建一个请求对象
        request.onreadystatechange = ()=>{
            console.log(request.readyState)
        }
        request.open('GET', '/xxxx')    // 配置参数
        request.send()    // 发送请求
    })
    
image.png
  1. 浏览器返回的状态码如果是3开头的,一定会发另一个请求,最终会得到一2开头或者以4开头的状态码,一般不管3开头的状态码

    myButton.addEventListener('click', (e)=>{
    let request = new XMLHttpRequest()    // 创建一个请求对象
    request.onreadystatechange = ()=>{
        // readyState等于4有两种情况,一种是成功,一种是失败
        if(request.readyState === 4){
            console.log('请求响应都结束了')
            if(request.status >=200 && request.status < 300){
                console.log('请求成功。')
                console.log(request.responseText)    // 读取响应的第四部分
            }else if(request.status >= 400){
                console.log('请求失败。')
            }
        }
    }
    request.open('GET', '/xxxx')    // 配置参数
    request.send()    // 发送请求
    })
    
    image.png
  2. XML是可以当做页面处理的,但是这个做饭已经过时了。每次都要写比较麻烦的过程去获取其中的数据


    image.png
  3. 我们想简单表示一些有结构的数据。有一个人叫道格拉斯发明了一种语言叫做JSON,这是一门新的语言,用于数据交换语言

  4. 后台是没有办法返回一个对象给前端的,返回的都是字符串,我们将返回的数据使用json格式的字符串返回


    image.png

    image.png
  5. 我们拿到字符串之后,怎么解析这个对应的字符串呢?可以使用window.JSON.parse,将字符串转成JS对象

    myButton.addEventListener('click', (e)=>{
        let request = new XMLHttpRequest()    // 创建一个请求对象
        request.open('GET', '/xxxx')    // 配置参数
        request.onreadystatechange = ()=>{
            if(request.readyState === 4){
                console.log('请求响应都结束了')
                if(request.status >=200 && request.status < 300){
                    console.log('请求成功。')
                    console.log(request.responseText)    // 读取响应的第四部分
                    console.log(typeof request.responseText)    // String
                    let string = request.responseText
                    // 把符合JSON语法的字符串转换成JS对应的值
                    let object = window.JSON.parse(string)
                    console.log(typeof object)
                    console.log(object.note)
                    console.log(object.note.from)
                }else if(request.status >= 400){
                    console.log('请求失败。')
                }
            }
        }
    
        request.send()    // 发送请求
    })
    
    image.png
  6. Ajax奠定了前端的基础

myButton.addEventListener('click', (e)=>{
 let request = new XMLHttpRequest()
 request.open('get', '/xxx') // 配置request
 request.send()
 request.onreadystatechange = ()=>{
   if(request.readyState === 4){
     console.log('请求响应都完毕了')
     console.log(request.status)
     if(request.status >= 200 && request.status < 300){
       console.log('说明请求成功')
       console.log(typeof request.responseText)
       console.log(request.responseText)
       let string = request.responseText
       // 把符合 JSON 语法的字符串
       // 转换成 JS 对应的值
       let object = window.JSON.parse(string) 
       // JSON.parse 是浏览器提供的
       console.log(typeof object)
       console.log(object)
       console.log('object.note')
       console.log(object.note)

     }else if(request.status >= 400){
       console.log('说明请求失败') 
     }

   }
 }
})

// 后端代码
 }else if(path==='/xxx'){
   response.statusCode = 200
   response.setHeader('Content-Type', 'text/json;charset=utf-8')
   response.setHeader('Access-Control-Allow-Origin', 'http://frank.com:8001')
   response.write(`
   {
     "note":{
       "to": "小谷",
       "from": "方方",
       "heading": "打招呼",
       "content": "hi"
     }
   }
   `)
   response.end()

使用ajax发送XML


  1. XML是一种文档类型,我们认识的DOM对象不止是用于HTML,还可以用于XML
  2. ajax最初诞生的时候就是为了使用responseXML,这是一个XML
  3. 后来这门语言被JSON替代
    const request = new XMLHttpRequest();
    request.open("GET", '/4.xml');
    request.onreadystatechange = () => {
        if(request.readyState === 4 && request.status === 200){
            const dom = request.responseXML;
            const text = dom.getElementsByTagName('warning')[0].textContent
            console.log(text.trim())
        }
    }
    request.send()
    

JSON —— 一门新语言


http://json.org
我们想简单表示一些有结构的数据。有一个人叫道格拉斯发明了一种语言叫做JSON,这是一门新的语言,用于数据交换语言

  1. JSON没有抄袭functionh和undefined
  2. JSON中字符串的字符串一定是在双引号里面
  3. JSON没有变量,无法引用,不能表示复杂的对象,只能表示哈希
  4. image.png
  5. JSON(JavaScript Object Notation)是一门独立语言
  6. JSON不是编程语言,是一种标记语言
  7. JSON可以表示什么?
    • {"name": "hahah", "age": "18"}
  8. 支持的数据类型
    • string-只支持双引号,不支持单引号和无引号
    • number-支持科学计数法
    • bool-true和false
    • null-没有undefined
    • object
    • array
    • 不支持函数,不支持变量(不支持引用)
  9. 使用ajax加载json
    • 使用JSON.parse转成对象,使用json代替ajax
    const request = new XMLHttpRequest();
    request.open("GET", '/5.json');
    request.onreadystatechange = () => {
        if(request.readyState === 4 && request.status === 200){
            const object = json.parse(request.response);
            myName.textContent = object.name
        }
    }
    request.send()
    
  10. window.JSON
    • JSON.parse
      • 将符合JSON语法的字符串转换成JS对应类型的类型
      • JSON字符串=>JS数据
      • 由于JSON只有六中类型,所以转成的数据也只有6种
      • 如果不符合JSON语法,则直接抛出一个Error对象
      • 一半用try catch捕获错误
    • JSON.stringify
      • 是JSON.parse的逆运算
      • JS数据=> JSON字符串
      • 由于JS的数据类型比JSON多,所以不一定会转换成功
      • 如果失败,就抛出一个Error对象

总结

  • HTTP是个框,什么都能往里装
    • 可以装HTML、CSS、JS、XML......
    • 记得设置正确的 Content-Type,这是好习惯
    • 只要你知道怎么解析这些内容,就可以使用这些内容
  • 解析方法
    • 得到CSS之后生成的style标签
    • 得到JS之后生成script标签
    • 得到HTML之后使用innerHTML和DOM API
    • 得到XML之后使用responseXML和DOM API
    • 不同类型的数据有不同类型的解析方法
  • AJAX可以用于数据分页

你可能感兴趣的:(AJAX)