AJAX 的前因后果

简要理解 AJAX

  1. 你才返回对象,你全家都返回对象("你"指的是响应内容的第四部分)
  2. JS 是一门语言,JSON 是另外一门语言,JSON 这门语言抄袭了 JS这门语言
  3. AJAX 就是用 JS set 请求和get 响应
  4. 响应的第四部分是字符串,能够用 JSON 语法表示一个对象,也能够用 JSON 语法表示一个数组,还能够用 XML 语法,还能够用 HTML 语法,还能够用 CSS 语法,还能够用 JS 语法,还能够用我自创的语法

如何发请求?

用 form 能够发请求,可是会刷新页面或新开页面
用 a 能够发 get 请求,可是也会刷新页面或新开页面
用 img 能够发 get 请求,可是只能以图片的形式展现
用 link 能够发 get 请求,可是只能以 CSS、favicon 的形式展现
用 script 能够发 get 请求,可是只能以脚本的形式运行(就是 JSONP 的实现原理)前端

有没有什么方式能够实现node

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

微软的突破

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

AJAX

Jesse James Garrett 讲以下技术取名叫作 AJAX:异步的 JavaScript 和 XML程序员

AJAX 技术包括如下四步:github

  1. 建立 AJAX 对象, 即 XMLHttpRequest
  2. 使用 XMLHttpRequest 发请求
  3. 服务器返回 XML 格式的字符串
  4. JS 解析 XML,并更新局部页面

AJAX demo

https://github.com/wojiaofeng...ajax

理解 AJAX

学 AJAX 以前,须要知道 HTTP 请求内容和 HTTP 响应内容的四个部分,以下chrome

问题: 老师的 key: alue有许多---的是须要背的吗?

请求内容:json

请求内容

响应内容: 后端

响应内容

同时还要知道怎么在 Chrome 上查看 HTTP request 和 HTTP response 跨域

选区_112.png

那么,AJAX 是什么呢?咱们能够画出 ” client 和 server “ 的关系图:

选区_113.png

AJAX 就是在 chrome 经过 XMLHttpRequest 对象, 构造(set)HTTP 请求和获取(get)HTTP 响应的技术

那么 AJAX 的具体实现方法是怎么样的呢?

  1. JS 设置(set)任意请求 header
    请求内容第一部分 request.open('get', '/xxx')
    请求内容第二部分 request.setRequestHeader('content-type','x-www-form-urlencoded')
    请求内容第四部分 request.send('a=1&b=2')
  2. JS 获取(get)任意响应 header
    响应内容第一部分 request.status / request.statusText
    响应内容第二部分 request.getResponseHeader() / request.getAllResponseHeaders()
    响应内容第四部分 request.responseText

jQuery 的 AJAX 实现代码迭代过程

如何肯定写的 AJAX 代码是否正确?将你写的代码放到 AJAX demo 的 main.js

初版:使用原生 js 中的 XMLHttpRequest 实现 ajax

//本身写的初版
myButton.addEventListener('click', function(){
  ajax()
})

function ajax(){
//至关于告诉浏览器我要set Http 请求了
  var request = new XMLHttpRequest()
//对应 http 请求的第一部分
  request.open("post", "/xxx")
//对应 http 请求的第二部分
  request.setRequestHeader("name", "rjj")
  request.setRequestHeader("name", "zzz")
//对应 http 请求的第三部分,仅仅是为了便于记忆
  request.onreadystatechange = function(){
    if(request.readyState === 4){
      if(request.status >= 200 && request.status < 300){
        console.log("成功")
        console.log("request.responseText")
        console.log(request.responseText)
      }else{
        console.log("失败")
        console.log(request)
      }
    }
  }
//对应 http 请求的第四部分
  request.send("xxxxxxxxx")
}

第二版:放到函数内

把初版中的function ajax(){}内写死的内容提取出来, 用变量获取, 代码以下:

//本身写的第二版
myButton.addEventListener('click', function(){
  ajax("post", "/xxx", {name:'rjj', sss:'zxxx'}, fffff, yyyyyy)
})

function ajax(method, path, header, successFn, failFn, body){
  var request = new XMLHttpRequest()

  request.open(method, path)

  for(var key in header){
    request.setRequestHeader(key, header[key])
  }

  request.onreadystatechange = function(){
    if(request.readyState === 4){
      if(request.status >= 200 && request.status < 300){
          //调用 ajax 函数的成功函数,而且往这个函数添加 request.responseText 变量做为第一个参数
        successFn.call(undefined, request.responseText)
      }else{
        failFn.call(undefined, request)
      }
    }
  }

  request.send(body)
}

function fffff(x){
  console.log(x)
  console.log("请求成功了")
}

function yyyyyy(x){
  console.log(x)
  console.log("请求失败了了")

}

第三版:更灵活的函数调用

第二版的函数调用实在太难用了, 根本不能在实际中使用, 我能不能改进一下?

我能不能像这样调用函数? 注意我能够改变每一个 key: value 的位置, 还能够不设置某个 key: value

ajax({
  method: "post",
  path: "/xxx",
  header:{
    name:"rjj",
    test:"rjj111",
    test2:"rjj2222"
  }
  body: "password=xxx",
  successFn: success,
  failFn: fail
})
myButton.addEventListener('click', function(){
  ajax({
    method: "post",
    header:{
      name: "xxx",
      zzz:'xxx',
    },
    successFnAA: function(x){
      console.log(x)
    },
    failFnAA: function(x){
      console.log(x)
    },
    path: "/xxx",
  })
})

function ajax(options){

  var method = options.method
  var path = options.path
  var header = options.header
  var successFn = options.successFnAA
  var failFn = options.failFnAA
  var body = options.body

  var request = new XMLHttpRequest()

  request.open(method, path)

  for(var key in header){
    request.setRequestHeader(key, header[key])
  }

  request.onreadystatechange = function(){
    if(request.readyState === 4){
      if(request.status >= 200 && request.status < 300){
        successFn.call(undefined, request.responseText)
      }else{
        failFn.call(undefined, request)
      }
    }
  }

  request.send(body)
}

注意:

  1. successFnAA 是参数, 参数的值是一个函数, 函数的内容是function(x){console.log(x)}
  2. 可是这个函数AA没有执行, 他是在 ajax 函数内部执行, 而且往函数AA添加了一个参数(request.responseText)
  3. 函数AA叫作 callback 函数

第四版: 把他放到自制的 jQuery 上

我想把原生的 AJAX 实现代码封装到我本身写的库,应该怎么办?

创造一个对象, 把第三版的 AJAX 函数挂到这个对象上便可

myButton.addEventListener("click", function(){
$.ajax(
  {
    method: "post",
    path: "/xxx",
    header:{
      name: "xxx",
      zzz:'xxx',
    },
    successFnAA: function(x){
      console.log(x)
    },
    failFnAA: function(x){
      console.log(x)
  } 
})
})

//创造对象
window.jQuery = function(nodeOrSelector){
  var nodes = {}
  return nodes
}

//将 AJAX 函数挂到对象上
window.jQuery.ajax = function(options){

  var method = options.method
  var path = options.path
  var header = options.header
  var successFn = options.successFnAA
  var failFn = options.failFnAA
  var body = options.body

  var request = new XMLHttpRequest()

  request.open(method, path)

  for(var key in header){
    request.setRequestHeader(key, header[key])
  }

  request.onreadystatechange = function(){
    if(request.readyState === 4){
      if(request.status >= 200 && request.status < 300){
        successFn.call(undefined, request.responseText)
      }else{
        failFn.call(undefined, request)
      }
    }
  }

  request.send(body)
}

//仅仅是简写,并不重要
window.$ = window.jQuery

第五版: 使用 ES6 将代码优化(析构赋值)

  1. 原代码:

    var method = options.method
    var path = options.path
    var header = options.header
    var successFn = options.successFn
    var failFn = options.failFn
    var body = options.body
  2. 使用 ES6 代码优化:

    let {method, path, header, successFn, failFn, body} = options
  3. 再次优化:

    将上一步的代码删除, 复制{method, path, header, successFn, failFn, body}

    放到window.jQuery.ajax = function(AAA){}的AAA处

第六版: 使用 promise 统一成功函数名和失败函数名

若是一个项目须要使用两个不一样的库,那么你就必须去看这个库的代码才能知道如何调用成功函数和失败函数, 因此咱们使用 promise 来统一函数名,调用这个库的时候就没必要考虑成功函数的名字

记住: return new Promise(function(resolve, reject){})

添加 promise 步骤

  1. 在 window.jQuery.ajax 函数内部, 剪切全部代码
  2. 在 window.jQuery.ajax 函数内部,添加return new Promise(function(resolve, reject){AAA})
  3. 在AAA区域复制代码
  4. 将 successFn 变成 resolve, 将 failFn 变成 reject

使用 promise

  1. 将调用 jQuery.ajax 中的 successFnAA 和 failFn 及其参数内容删除
  2. jQuery.ajax()以后添加.then,其中第一个参数表示成功函数, 第二个参数表是失败函数
myButton.addEventListener("click", function() {
    jQuery.ajax({
        method: "post",
        path: "/xxx",
        header: {
            name: "xxx",
            zzz: 'xxx'
        }
    }).then(function () {
        console.log(1)
    }, function () {
        console.log(2)
    })


})


window.jQuery = function(nodeOrSelector){
    var nodes = {}
    return nodes
}



window.jQuery.ajax = function(options){
    return new Promise(function (resolve, reject) {

        var method = options.method
        var path = options.path
        var header = options.header
        var body = options.body

        var request = new XMLHttpRequest()

        request.open(method, path)

        for (var key in header) {
            request.setRequestHeader(key, header[key])
        }

        request.onreadystatechange = function(){
            if (request.readyState === 4) {
                if (request.status >= 200 && request.status < 300) {
                    resolve.call(undefined, request.responseText)
                } else {
                    reject.call(undefined, request)
                }
            }
        }
        request.send(body)
    })
}

JSON —— 一门新语言

http://json.org

同源策略

只有 协议+端口+域名 如出一辙才容许发 AJAX 请求

如出一辙如出一辙如出一辙如出一辙如出一辙如出一辙如出一辙如出一辙

  1. http://baidu.com 能够向 http://www.baidu.com 发 AJAX 请求吗 no
  2. http://baidu.com:80 能够向 http://baidu.com:81 发 AJAX 请求吗 no

浏览器必须保证
只有 协议+端口+域名 如出一辙才容许发 AJAX 请求
CORS 能够告诉浏览器,我俩一家的,别阻止他

突破同源策略 === 跨域

Cross-Origin Resource Sharing
C O 资源R S

CORS 跨域

A网站的前端程序员打电话告诉B网站的后端程序员

A前: 我想和你的网站进行交互, 你赞成吗?

B后: 我赞成

而后B后端程序员就在后台代码(响应内容)写上这一句代码:

response.setHeader("Access-Control-Allow-Origin", "http://A.com:8001"), 网站是A网站的前端程序员告诉给B后端

这就是 CORS 跨域

个人 github 博客地址: https://github.com/wojiaofeng...以为好的能够 start ,O(∩_∩)O谢谢

相关文章
相关标签/搜索