资讯专栏INFORMATION COLUMN

AJAX 的来龙去脉

fnngj / 2354人阅读

摘要:简要理解你才返回对象,你全家都返回对象你指的是响应内容的第四部分是一门语言,是另一门语言,这门语言抄袭了这门语言就是用请求和响应响应的第四部分是字符串,可以用语法表示一个对象,也可以用语法表示一个数组,还可以用语法,还可以用语法,还可以用语

简要理解 AJAX

你才返回对象,你全家都返回对象("你"指的是响应内容的第四部分)

JS 是一门语言,JSON 是另一门语言,JSON 这门语言抄袭了 JS这门语言

AJAX 就是用 JS set 请求和get 响应

响应的第四部分是字符串,可以用 JSON 语法表示一个对象,也可以用 JSON 语法表示一个数组,还可以用 XML 语法,还可以用 HTML 语法,还可以用 CSS 语法,还可以用 JS 语法,还可以用我自创的语法

如何发请求?

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

有没有什么方式可以实现

get、post、put、delete 请求都行

想以什么形式展示就以什么形式展示

微软的突破

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

AJAX

Jesse James Garrett 讲如下技术取名叫做 AJAX:异步的 JavaScript 和 XML

AJAX 技术包括以下四步:

创建 AJAX 对象, 即 XMLHttpRequest

使用 XMLHttpRequest 发请求

服务器返回 XML 格式的字符串

JS 解析 XML,并更新局部页面

AJAX demo

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

理解 AJAX

学 AJAX 之前,需要知道 HTTP 请求内容和 HTTP 响应内容的四个部分,如下

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

请求内容:

响应内容:

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

那么,AJAX 是什么呢?我们可以画出 ” client 和 server “ 的关系图:

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

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

JS 设置(set)任意请求 header
请求内容第一部分 request.open("get", "/xxx")
请求内容第二部分 request.setRequestHeader("content-type","x-www-form-urlencoded")
请求内容第四部分 request.send("a=1&b=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)
}

注意:

successFnAA 是参数, 参数的值是一个函数, 函数的内容是function(x){console.log(x)}

但是这个函数AA没有执行, 他是在 ajax 函数内部执行, 并且往函数AA添加了一个参数(request.responseText)

函数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 将代码优化(析构赋值)

原代码:

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

使用 ES6 代码优化:

let {method, path, header, successFn, failFn, body} = options

再次优化:

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

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

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

如果一个项目需要使用两个不同的库,那么你就必须去看这个库的代码才能知道如何调用成功函数和失败函数, 所以我们使用 promise 来统一函数名,调用这个库的时候就不必考虑成功函数的名字

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

添加 promise 步骤

在 window.jQuery.ajax 函数内部, 剪切所有代码

在 window.jQuery.ajax 函数内部,添加return new Promise(function(resolve, reject){AAA})

在AAA区域复制代码

将 successFn 变成 resolve, 将 failFn 变成 reject

使用 promise

将调用 jQuery.ajax 中的 successFnAA 和 failFn 及其参数内容删除

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 请求

一模一样一模一样一模一样一模一样一模一样一模一样一模一样一模一样

http://baidu.com 可以向 http://www.baidu.com 发 AJAX 请求吗 no

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谢谢

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/113026.html

相关文章

  • AJAX 来龙去脉

    摘要:简要理解你才返回对象,你全家都返回对象你指的是响应内容的第四部分是一门语言,是另一门语言,这门语言抄袭了这门语言就是用请求和响应响应的第四部分是字符串,可以用语法表示一个对象,也可以用语法表示一个数组,还可以用语法,还可以用语法,还可以用语 简要理解 AJAX 你才返回对象,你全家都返回对象(你指的是响应内容的第四部分) JS 是一门语言,JSON 是另一门语言,JSON 这门语言抄...

    Miracle 评论0 收藏0
  • 爬虫问题总结

    摘要:编码我们发现,中有时候存在中文,这是就需要对进行编码。可以先将中文转换成编码,然后使用方法对参数进行编码后传递。 本文档对日常学习中用 python 做数据爬取时所遇到的一些问题做简要记录,以便日后查阅,部分问题可能因为认识不到位会存在一些误解,敬请告知,万分感谢,共同进步。 估算网站规模 该小节主要针对于整站爬取的情况。爬取整站之前,肯定是要先对一个网站的规模进行估计。这是可以使用g...

    nanfeiyan 评论0 收藏0
  • [译] 深入理解 Promise 五部曲:1. 异步问题

    摘要:当引擎开始执行一个函数比如回调函数时,它就会把这个函数执行完,也就是说只有执行完这段代码才会继续执行后面的代码。当条件允许时,回调函数就会被运行。现在,返回去执行注册的那个回调函数。 原文地址:http://blog.getify.com/promis... 在微博上看到有人分享LabJS作者写的关于Promise的博客,看了下觉得写得很好,分五个部分讲解了Promise的来龙去脉。从...

    CHENGKANG 评论0 收藏0
  • 零基础前端开发初学者应如何系统地学习?

    摘要:在有了基础之后,进一步学习内容包括框架。前端学习交流群禁止闲聊,非喜勿进。代码提交前必须做的三个事情检查所有变更跑一边单元测试手动运行一遍所有 网站开发开发大致分为前端和后端,前端主要负责实现视觉和交互效果,以及与服务器通信,完成业务逻辑。其核心价值在于对用户体验的追求。可以按如下思路学习系统学习: 基础知识: html + css 这部分建议在 w3school 在线教程上学习,边...

    JouyPub 评论0 收藏0

发表评论

0条评论

fnngj

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<