AJAX

作者: darkTi | 来源:发表于2018-02-27 23:59 被阅读0次

    如何发请求?

    • 用form可以发post或get请求,但是但是会刷新页面或新开页面
    • 用 a 可以发 get 请求,但是也会刷新页面或新开页面
    • 用 img 可以发 get 请求,但是只能以图片的形式展示
    • 用 link 可以发 get 请求,但是只能以 CSS、favicon 的形式展示
    • 用 script 可以发 get 请求,但是只能以脚本的形式运行

    所以急需一种API可以满足以下两个要求:

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

    微软的突破

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

    AJAX

    • Jesse James Garrett 将如下技术取名叫做 AJAX(Async JavaScript And XML):异步的 JavaScript 和 XML
    1. 使用 XMLHttpRequest 发请求
    2. 服务器返回 XML 格式的字符串(现在都使用JSON来代替XML)
    3. JS 解析 XML,并更新局部页面
    • AJAX就是用JS去发请求
    • 响应的第四部分是字符串,可以用 JSON 语法表示一个对象,也可以用 JSON 语法表示一个数组,还可以用 XML 语法,还可以用 HTML 语法,还可以用 CSS 语法,还可以用 JS 语法,还可以用自创的语法
    • 示例
    myButton.addEventListener('click',(e)=>{
      let request = new XMLHttpRequest()
      request.open('get','/xxx')//配置request
      request.send()
      setInterval(()=>{console.log(request.readyState)},1)
    })
    
    结果: 2.png

    XMLHttpRequest.readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态


    3.png
    图2中没有出现0、2、3是因为他们运行太快,没有捕捉到;每一次都会按照0~4的状态来运行。
    由此可见,每毫秒来捕捉也无法得到所有的状态,那么有没有一个属性只要状态发生变化就通知我?有的。
    request.onreadystatechange 
    

    如何使用 XMLHttpRequest

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

    原生JS写一个AJAX

    let request = new XMLHttpRequest()//声明
      request.open('get','/xxx')//配置request
      request.send()//发送
      request.onreadystatechange = ()=>{
        if(request.readyState === 4){
          if(request.status >= 200 && request.status < 300){
            let string = request.responseText
            let object = window.JSON.parse(string)//解析
          }
        }
      }
    

    JSON

    1. JSON是由Douglas Crockford(道格拉斯克罗克福德)构想设计的数据交换语言,它是一门新的语言,与JavaScript不一样
    2. JS VS JSON 4.png

    同源策略

    • 即只有 协议+端口+域名 一模一样才允许发 AJAX 请求,否则浏览器上的任何网页都可被随意盗取信息
    1. http://baidu.com 可以向 http://www.baidu.com 发 AJAX 请求吗? 不可以
    2. http://baidu.com:80 可以向 http://baidu.com:81 发 AJAX 请求吗? 不可以
      要保持一模一样才能发AJAX请求
    • 如果想要请求别的域名,那么就给它的后台打电话,通过两种方式处理①JSONP(但它不能发POST请求);②CORS跨域;(用哪种方法都可以)

    CORS跨域

    • Cross-Origin Resource Sharing(跨站资源共享)
    • 只需在需要共享的那个域名下加上一句代码
        response.setHeader('Access-Control-Allow-Origin', 'http://frank.com:8001')
    

    就是告诉浏览器http://frank.com:8001这个网站是我的朋友,你不要拦它,可以让它读我的内容

    AJAX的所有功能

    • 客户端的JS发起请求(浏览器上的)
    • 服务端的JS发送响应(Node.js上的)
    1. JS 可以设置任意请求 header
      第一部分 request.open('get', '/xxx') //浏览器默认get请求是不显示第四部分的
      第二部分 request.setRequestHeader('Content-Type','x-www-form-urlencoded')
      第四部分 request.send('a=1&b=2') //请求体
    2. JS 可以获取任意响应 header
      第一部分 request.status //状态码
      request.statusText //状态码的文字解释
      第二部分 request.getResponseHeader('Content-Type') //获取指定的响应头
      request.getAllResponseHeaders() //获取全部的响应头
      第四部分 request.responseText //响应体
      至此,HTTP是如何请求响应的,就大致了解了:
      ①客户端通过AJAX设置请求头,发送请求到服务器端(服务器端需要指定端口)
      ②服务器端设置响应并发送到客户端(客户端不需要指定端口)

    用jQuery封装AJAX

    window.jQuery = function(nodeOrSelector){
      let nodes = {}
      nodes.addClass = function(){}
      return nodes
    }
    window.jQuery.ajax = function(url,method,body,success,fail){
      let request = new XMLHttpRequest()
      request.open(method,url)//配置request
      request.onreadystatechange = ()=>{
        if(request.readyState === 4){
          if(request.status >= 200 && request.status < 300){
           success.call(undefined,request.responseText)
          }else if(request.status >= 400){
            fail.call(undefined,request)
          }
        }
      }
      request.send(body)
    }
    
    window.$ = window.jQuery
    
    myButton.addEventListener('click',(e)=>{
      window.jQuery.ajax(
       '/xxx',
       'post',
       'a=1&&b=2',
       ()=>{console.log(1)},
       ()=>{console.log(2)}
      )
    })
    

    但是上面最大的不足就是ajax函数中参数太多,容易造成忘记每个参数代表什么,所以需要作出优化,把所有参数转换成一个对象传进去

    window.jQuery.ajax = function(options){
      
      let url = options.url
      let method = options.method
      let body = options.body
      let success = options.success
      let fail = options.fail
      let headers = options.headers
    ......
    }
    

    利用ES6的解构赋值语法优化参数

    window.jQuery.ajax = function(options){
      let {url,method,body,success,fail,headers} = options
    ......
    }
    

    继续优化

    window.jQuery.ajax = function({url,method,body,success,fail,headers}){
    ......
    }
    

    Promise

    • 因为成功需要回调成功函数,失败要回调失败函数,但是每个库的成功失败回调函数名是不一样的,例如image.onload(成功),image.onerror(失败),我们不可能一一地去查每个库回调函数的名字,所以就引入promise(promise是window下的全局属性),利用promise的then属性。
    then(()=>{},()=>{}) //成功执行第一个函数,失败执行第二个函数
    
    • 利用jQuery的promise属性(不要忘记引入jQuery)
    myButton.addEventListener('click',(e)=>{
      $.ajax(
       {url:'/xxx',
       method:'post',
       headers:{
         'Content-Type':'x-www-form-urlencoded',
         'doudou':'18'
        }   
       }).then(
         (text)=>{console.log(text)},
         (request)=>{console.log(request)}
        )
    })
    
    • 自己定义promise来封装AJAX
    window.jQuery = function(nodeOrSelector){
      let nodes = {}
      nodes.addClass = function(){}
      nodes.html = function(){}
      return nodes
    }
    window.$ = window.jQuery
    window.Promise = function(fn){
      return {
        then: function(){}
      }
    }
    
    window.jQuery.ajax = function({url,method,body,headers}){
      return new Promise(function(resolve, reject){ //这六个单词是最重要的
        let request = new XMLHttpRequest()
        request.open(method,url)//配置request
        for(let key in headers){ //遍历对象中的属性
          let value = headers[key]
          request.setRequestHeader(key,value)
        }
        request.onreadystatechange = ()=>{
          if(request.readyState === 4){
            if(request.status >= 200 && request.status < 300){
             resolve.call(undefined,request.responseText)
            }else if(request.status >= 400){
              reject.call(undefined,request)
            }
          }
        }
        request.send(body)
      })
    
    }
    myButton.addEventListener('click',(e)=>{
      let promise = window.jQuery.ajax(
       {url:'/xxx',
       method:'post',
       headers:{
         'Content-Type':'x-www-form-urlencoded',
         'doudou':'18'
        }   
       })
       promise.then(
         (text)=>{console.log(text)},
         (request)=>{console.log(request)}
        )
    })
    

    相关文章

      网友评论

          本文标题:AJAX

          本文链接:https://www.haomeiwen.com/subject/mzhmxftx.html