谈谈XMLHttpRequest实现Ajax与跨域问题

文章目录

    • 一、XMLHttpRequest对象
      • 后端准备
      • 实现一个简易的ajax请求
      • 1.open()
      • 2.xhr.readyState
      • 3.xhr.onreadystatechange()
      • 4.xhr.status
      • 5.send()
    • 二、同源策略与跨域
      • 1.什么是跨域?
      • 2.同源策略
    • 三、实现跨域的几种方式
      • 1.JSONP实现跨域
        • JSONP原理
        • JSONP实现
      • 2.CORS服务端支持
        • 对于简单请求
        • 对于非简单请求
        • 注意
      • 3.HTTP代理(http proxy)

本文以使用一个XMLHttpRequest对象发起GET请求开始,探讨同源策略与跨域和跨域的实现。

一、XMLHttpRequest对象

MDN:XMLHttpRequest

XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest 在 AJAX 编程中被大量使用。

使用XMLHttpRequest 来发送 HTTP 请求以实现网站和服务器之间的数据交换。

发送一个 HTTP 请求,需要创建一个 XHR 对象,打开一个 URL,最后发送请求。当所有这些事务完成后,该对象将会包含一些诸如响应主体或 HTTP status 的有用信息。

后端准备

我这里使用了express简单搭建了一个服务。

app.js

const express = require('express');
const app = express();
app.all('*', function (req, res, next) {
     
  res.header('Access-Control-Allow-Origin', '*'); // 跨域配置
  next();
});
app.get('/api/test', (req, res) => {
     
  res.send('hello express');
});
app.listen(3000, () => {
     
  console.log('server running at port 3000');
});

实现一个简易的ajax请求

const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:3000/api/test', true);
xhr.onreadystatechange = function () {
     
  if (xhr.readyState === 4) {
     
    if (xhr.status === 200) {
     
      alert(xhr.responseText);
    }
  }
}
xhr.send(null);

1.open()

XMLHttpRequest.open() 方法初始化一个请求

/**
 * @param method HTTP方法
 * @param url 路径
 * @param async 是否异步
 */
xhr.open(method, url, async);

2.xhr.readyState

XMLHttpRequest.readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态。一个 XHR 代理总是处于下列状态中的一个:

状态 描述
0 UNSENT 代理被创建,但尚未调用 open() 方法。
1 OPENED open() 方法已经被调用。
2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得。
3 LOADING 下载中; responseText 属性已经包含部分数据。
4 DONE 下载操作已完成。

我们如何查看readyState的变化?这就需要XMLHttpRequest.onreadystatechange

3.xhr.onreadystatechange()

只要 readyState 属性发生变化,就会调用相应的处理函数。这个回调函数会被用户线程所调用。XMLHttpRequest.onreadystatechange 会在 XMLHttpRequest 的readyState 属性发生改变时触发 readystatechange 事件的时候被调用。

readyState 的值改变的时候,callback 函数会被调用。

我们需要将回调函数的定义提到 open() 函数之前。因为open调用,请求初始化,readyState会从初始的0变成1,我们就不能打印出完整过程。

const xhr = new XMLHttpRequest();
console.log('UNSENT:', xhr.readyState); // 打印初始readyState
xhr.onreadystatechange = function () {
     
  console.log('onreadystatechange:', xhr.readyState);
};
xhr.open('GET', 'http://127.0.0.1:3000/api/test', true);
xhr.send(null);

在浏览器中查看

谈谈XMLHttpRequest实现Ajax与跨域问题_第1张图片

4.xhr.status

只读属性 XMLHttpRequest.status返回了响应中的数字状态码。在请求完成前和XMLHttpRequest 出错,status的值为0。 status码是标准的HTTP status codes。

查看完整状态的代码如下

const xhr = new XMLHttpRequest();
console.log(`UNSENT:readyState=${
       xhr.readyState};status=${
       xhr.status}`);
xhr.onreadystatechange = function () {
     
  console.log(`onreadystatechange=${
       xhr.readyState};status=${
       xhr.status}`);
};
xhr.open('GET', 'http://127.0.0.1:3000/api/test', true);
xhr.send(null);

在浏览器中查看

谈谈XMLHttpRequest实现Ajax与跨域问题_第2张图片

5.send()

XMLHttpRequest.send() 方法用于发送 HTTP 请求。如果是异步请求(默认为异步请求),则此方法会在请求发送后立即返回;如果是同步请求,则此方法直到响应到达后才会返回。XMLHttpRequest.send() 方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。

XMLHttpRequest.send(body)

注:在 open()send() 之间,我们可以通过 XMLHttpRequest.setRequestHeader() 设置请求头等参数。

通过以上的步骤,我们就可以发送一个ajax请求。

二、同源策略与跨域

1.什么是跨域?

跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。

2.同源策略

同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,会导致很多安全问题。

同源是指"协议+域名+端口"三者相同。

同源策略限制了以下行为:

  • Cookie、LocalStorage 和 IndexDB 等存储性内容
  • DOM 和 JS 对象无法获取
  • Ajax 请求不能发送

注意:一定要注意跨域是浏览器的限制,当我们用抓包工具抓取接口数据,是可以看到接口以及把数据返回回来了,只是浏览器的限制,我们获取不到数据。用postman请求接口能够请求到数据,这些再次印证了跨域是浏览器的限制

三、实现跨域的几种方式

1.JSONP实现跨域

JSONP (JSON with Padding ) json填充?

JSONP 是为解决跨域问题搞出来的一种获取数据的方式

JSONP原理

原理:在html页面中通过相应的标签从不同域名下加载静态资源文件是被浏览器允许的

加载图片、css、js可无视同源策略。

用处:img可用于统计打点,可使用第三方统计服务;link、script可使用CDN。利用script可实现JSONP跨域

<img src="跨域的图片地址" />
<link href="跨域的css地址" />
<script src="跨域的js地址">script>

要点:

  • 利用

你可能感兴趣的:(JavaScript,ajax跨域问题,jsonp,ajax,javascript,http)