# Ajax

  • Ajax(Asynchronous JavaScript and XML),异步 JavaScript 和 XML
  • 作用:增强用户体验——可以在用户浏览网页的同时与服务器进行异步交互和实现网页内容的局部更新
  • Ajax 应用的工作过程
    1. JavaScript 使用 XMLHttpRequest 对象(简称 XHR)向服务器发送请求
    2. JavaScript 使用 XMLHttpRequest 对象解析服务器响应数据
    3. JavaScript 通过操作 DOM 动态更新 HTML 页面

# XMLHttpRequest 对象 (opens new window)

  • 属性
    responseType: 响应信息为二进制数据时需设置 xhr.responseType = "blob";
    onreadystatechange:指定当 readyState 属性改变时的事件处理句柄
    onload: 请求成功完成时调用的函数
    readyState:返回 XMLHTTP 请求的当前状态(4 表示数据接收完毕)
    status:返回当前请求的 http 状态码(200 表示 OK)
    response: 响应信息
    responseText:将响应信息作为字符串返回
    responseXML:将响应信息格式化为 Xml Document 对象并返回

  • 构造函数:new XMLHttpRequest()

  • 实例方法
    open(bstrMethod, bstrUrl, varAsync):创建一个 http 请求,并指定此请求的发送方法(GET 或 POST),请求的 URL,是否为异步请求(默认为 true)
    setRequestHeader(bstrHeader, bstrValue):设置请求的某个 http 头,POST 请求需设置 "Content-Type" 为 "application/x-www-form-urlencoded"
    send(data):发送请求到 http 服务器并接收回应,data 为表单参数

// 创建 XHR 对象
var xhr = new XMLHttpRequest();
// xhr.withCredentials = true; // 设置跨域请求时是否携带 cookie
// 监听 readyState 状态,处理响应
xhr.onreadystatechange = function(callback) {
    if (xhr.readyState == 4) {
        if(xhr.status == 200) {
              callback(xhr.responseText);
        } else {
            ...
        }
    }
};
// 创建请求
xhr.open("get", "/gettime.do?" + new Date().getTime(), true);
// 发送请求
xhr.send();

// POST 请求
xhr.open("post", "http://localhost/user");
xhr.send(formdata);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# FormData 对象

  • formData 是 Ajax2.0(XMLHttpRequest Level 2)新提出的接口,利用 FormData 对象可以将 form 表单元素的 name 与 value 进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率

  • 构造函数
    new FormData():创建一个空对象实例
    new FormData(document.getElementById("myForm")):用表单来初始化

  • 对象方法
    append():向 FormData 中添加新的属性值,FormData 对应的属性值存在也不会覆盖原值,而是新增一个值,如果属性不存在则新增一项属性值set():给 FormData 设置属性值,如果 FormData 对应的属性值存在则覆盖原值,否则新增一项属性值delete():从 FormData 对象里面删除一个键值对get():返回在 FormData 对象中与给定键关联的第一个值getAll():返回一个包含 FormData 对象中与给定键关联的所有值的数组
    has():返回一个布尔值表明 FormData 对象是否包含某些键
    keys():返回一个包含所有键的 iterator 对象
    values():返回一个包含所有值的 iterator 对象

# 跨域资源访问

  • 同源策略:限制从一个源加载的文档或脚本与来自另一个源的资源进行交互(同源是指协议、域名、端口都相同)
  • 注意:同源策略只是浏览器的安全策略,不是 HTTP 协议的一部分

# CORS

  • CORS (opens new window) 是一个 W3C 标准,全称是“跨域资源共享”(Cross-Origin Resource Sharing)

  • 跨域资源共享(CORS)标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

  • 普通跨域请求,只需服务端设置 Access-Control-Allow-Origin 即可,前端无须设置;若要请求时携带 cookie,则前后端都需要设置(所读取的 cookie 为跨域请求接口所在域的 cookie,而非当前页)

  • OPTIONS 预检请求的 Response Headers

    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Auth-Key, Accept, Accept-Encoding, Accept-Language, Host, Referer, User-Agent
    Access-Control-Allow-Methods: GET, POST, OPTIONS
    Access-Control-Allow-Origin: http://app1.example.com
    Access-Control-Max-Age: 1728000
    Connection: keep-alive
    Content-Length: 0
    Date: Wed, 02 Sep 2020 16:26:35 GMT
    Server: nginx/1.16.1
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

# Frame 代理

# Nginx 代理

location / {
    #add_header Access-Control-Allow-Origin *; # 设置为 * 时,浏览器将不会发送 cookie,即使在 XHR 设置了 withCredentials(当前端跨域访问不带 cookie 时,可为 *)
    add_header Access-Control-Allow-Origin $scheme://$host;
    add_header Access-Control-Allow-Credentials true; # 该值只能是 true,否则不返回,为 true 时,Access-Control-Allow-Origin 不能为 *
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Auth-Key, Accept, Accept-Encoding, Accept-Language, Host, Referer, User-Agent';

    if ($request_method = 'OPTIONS') {
        return 204;
    }
}
1
2
3
4
5
6
7
8
9
10
11

# JSONP

  • JSONP(JSON with padding),填充式 JSON 或参数式 JSON,一种跨域读取数据的技术
  • JSONP 由两部分组成:回调函数是当响应到来时应该在页面中调用的函数,回调函数的名字一般是在请求中指定;数据是传入回调函数中的 JSON 数据
  • 可通过使用动态 <script > 标签来实现:为 src 属性指定一个跨域 URL,返回的数据会调用 js 解释器进行解析
Updated at: 2021-09-21 19:25:53