谈谈AJAX(一)

1. 概述

浏览器与服务器之间,采用 HTTP 协议通信。用户在浏览器地址栏键入一个网址,或者通过网页表单向服务器提交内容,这时浏览器就会向服务器发出 HTTP 请求。

2005年2月,AJAX 这个词第一次正式提出,它是 Asynchronous JavaScript and XML 的缩写,指的是通过 JavaScript 的异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页。
后来,AJAX 这个词就成为 JavaScript 脚本发起 HTTP 通信的代名词,也就是说,只要用脚本发起通信,就可以叫做 AJAX 通信。

具体来说,AJAX 包括以下几个步骤。

  1. 创建 XMLHttpRequest 实例
  2. 发出 HTTP 请求
  3. 接收服务器传回的数据
  4. 更新网页数据

概括起来,就是一句话,AJAX 通过原生的 XMLHttpRequest 对象发出 HTTP 请求,得到服务器返回的数据后,再进行处理。

一旦拿到服务器返回的数据,AJAX 不会刷新整个网页,而是只更新网页里面的相关部分,从而不打断用户正在做的事情。

注意,AJAX 只能向同源网址(协议、域名、端口都相同)发出 HTTP 请求,如果发出跨域请求,就会报错。

2. 如何发请求?(背景)

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

提出需求:如何不受限制的发请求?

  • get post delete请求都行
  • 想以什么形式展示就以什么形式展示

3. 微软的突破

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

可这样使用XMLHttpRequest:
var x = new XMLHttpRequest()

注意:XMLHttpRequest 是 window下的全局对象

4. AJAX(异步的 JavaScript 和 XML)

Jesse James Garrett 将如下技术点的方案取名叫做 AJAX:异步的 JavaScript 和 XML

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

5. 如何使用 XMLHttpRequest

5.1 XMLHttpRequest对象用法例子

客户端代码:

let request = new XMLHttpRequest();  //创建一个XMLHttpRequest

request.onreadystatechange = function(){
  // 通信成功时,状态值为4
  if (request.readyState === 4){
    if (request.status === 200){
      console.log(request.responseText);
    } else {
      console.error(request.statusText);
    }
  }
};

request.onerror = function (e) {
  console.error(request.statusText);
};

request.open('GET', '/endpoint', true); //配置
request.send(null);  //发送

服务器端代码:

if(path === '/'){
    response.statusCode = 200
    let string = fs.readFileSync('./index.html') 
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(string)
    response.end()
  }
  • http 请求的路径都是绝对路径.所以都是以 / 开头
  • 设置响应头中的Content-Type,response.setHeader('Content-Type', 'text/html;charset=utf-8'),即要求浏览器以HTML的语法解析这段字符串!
  • 对于HTTP来说,响应的第四部分始终都是字符串,因为response.write(string)返回的是字符串,我们给浏览器返回了符合html格式的字符串。

5.2 XMLHttpRequest 的实例属性

  • XMLHttpRequest.readyState
    XMLHttpRequest.readyState返回一个整数,表示实例对象的当前状态。该属性只读。
    4,表示服务器返回的数据已经完全接收,或者本次接收已经失败。
    通信过程中,每当实例对象发生状态变化,它的 readyState 属性的值就会改变。
var xhr = new XMLHttpRequest();

if (xhr.readyState === 4) {
  // 请求结束,处理服务器返回的数据
} else {
  // 显示提示“加载中……”
}

上面代码中,xhr.readyState 等于 4 时,表明脚本发出的 HTTP 请求已经完成。其他情况,都表示 HTTP 请求还在进行中。

  • XMLHttpRequest.onreadystatechange
    实例的 readyState属性变化,就会执行这个属性。
  • XMLHttpRequest.responseText
    XMLHttpRequest.responseText 属性返回从服务器接收到的字符串,该属性为只读。
  • XMLHttpRequest.status
    XMLHttpRequest.status属性返回一个整数,表示服务器回应的 HTTP 状态码。
    基本上,只有2xx和304的状态码,表示服务器返回是正常状态。
if (xhr.readyState === 4) {
  if ( (xhr.status >= 200 && xhr.status < 300)
    || (xhr.status === 304) ) {
    // 处理服务器的返回数据
  } else {
    // 出错
  }
}

6. 使用JSON解析响应的第四部分

XML语言结构的数据不好用且已经过时了,现使用JSON替代XML。
JSON是一门数据格式化语言,用来表示数据。
JSON官网:JSON

6.1 语法快速过

  1. JS的数据类型仅剩 symbolundefinedfunction 没抄
  2. 铁轨图(从左往右看)
  JS      VS      JSON
undefined         没有
null              null
'janice'          "janice"
['a','b']         ["a","b"]
{name: 'janice'}  {"name":"janice"}
function fn(){}   没有
var a = {}        搞不定(没有变量)
a.self = a        搞不定(没有变量)
{__proto__}       没有原型链

区别:

  • JSON没有抄袭 functionundefined
  • JSON的字符串 string首尾必须是 双引号 "

6.2 如何使用JSON

if (path === '/xxx') {
  response.statusCode = 200
  response.setHeader('Content-Type', 'text/json;charset=utf-8')
  response.write(`
  {
    "note":{
      "to": "Rose",
      "from": "Jack",
      "heading": "经典片段",
      "content": "You jump,I jump."
    }
  }
  `)
  response.end()
}

服务器返回的是字符串,恰巧这个字符串刚好符合JSON对象的语法格式。

前端收到响应后:

if(request.status >= 200 && request.status < 300){
  console.log('说明请求成功')
  let string = request.responseText
  // 把符合 JSON 语法的字符串转换成 JS 对应的值
  let object = window.JSON.parse(string) 
  // JSON.parse 是浏览器提供的
}else if(request.status >= 400){
  console.log('说明请求失败') 
}

7. 同源策略

只有 协议+端口+域名 一模一样才允许发 AJAX 请求

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

浏览器必须保证:
只有 协议+端口+域名 一模一样才允许发 AJAX 请求
CORS 可以告诉浏览器,我俩一家的,别阻止他

8. CORS 跨域

CORS(Cross-origin resource sharing),全称是“跨域资源共享”,是一个 W3C 标准。它允许浏览器向跨域的服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。

在代码中添加CORS头即可跨域:

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": "Rose",
      "from": "Jack",
      "heading": "经典片段",
      "content": "You jump,I jump."
    }
  }
  `)
  response.end()
}

注意:JSONP不能发起POST请求,要POST只能用CORS

彩蛋

面试问题:请使用原生JS发送Ajax请求

mybutton.addEventListener('click', (e) => {
  let request = new XMLHttpRequest()
  request.open('get', 'http://jack.com:8002/xxx')  
  //配置request 参数分别为方法和路径
  request.send()
  request.onreadystatechange = () => {
    if (request.readyState === 4) {
      if (request.status >= 200 && request.status < 300) {
        // 把符合 JSON 语法的字符串转换成 JS 对应的值
        let string = request.responseText
        // JSON.parse 是浏览器提供的
        let object = window.JSON.parse(string)
        console.log(object.note)
      } else if (request.status >= 400) {
        console.log('请求失败')
      }
    }
  }
})

参考链接

  1. 阮一峰,JavaScript 教程—XMLHttpRequest 对象
  2. 写代码啦
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352