原生JS实现一个Ajax跨域请求

本文深入解析Ajax(异步JavaScript和XML)的工作原理,包括其核心对象的创建、监听事件、设置请求方式、发送数据及处理响应结果。通过实例演示了如何使用Ajax实现网页的异步更新,提高用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么Ajax

在现实Ajax之前,我们需要了解下什么Ajax?

Asynchronous JavaScript + XML(异步 JavaScript 和 XML), 其本身不是一种新技术,而是一个在 2005 年被 Jesse James Garrett 提出的新术语,用来描述一种使用现有技术集合的‘新’方法。

当使用结合了这些技术的 AJAX 模型以后, 网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。

异步交互

接下来便要弄清楚什么是异步交互。

所谓异步交互,就是指指发送一个请求,不需要等待返回,随时可以再发送下一个请求。同步交互与异步交互的区别在于同步交互需要等待结果,而异步交互不需要等待。

举个简单的例子就是当点击某个按钮后,程序会去请求一些数据,而这个过程整个页面是不会刷新的。如下图所示,异步获取一言并且显示在页面中

e1137ef9-a733-41df-a6bb-af0e14452124

快速开始

一:核心对象

关于核心对象:https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest

核心对象是实现Ajax的关键所在,因为后边的一切方法都是基于这个核心对象进行操作。创建核心对象的方式固定,但需要注意的问题就是浏览器兼容问题(注意是IE)。

  • 谷歌、火狐、safari等浏览器

    使用new XMLHttpRequest()的方式进行创建

  • IE 7+

    使用new ActiveXObject("Msxml2.XMLHTTP")方式进行创建

  • IE 6-

    使用new ActiveXObject("Microsoft.XMLHTTP")方式进行创建

为了方便后期的使用,我会将其赋予window对象。并通过一个匿名函数,进行自动调用。

(function () {
  function createXMLHttpRequest() {
    var httpRequest;
    if (window.XMLHttpRequest) {
      // 适用于非IE浏览器
      httpRequest = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
      //   适用于IE浏览器
      try {
        // IE 7+
        httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
      } catch (e) {
        try {
          //   IE 6-
          httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) {}
      }
    }
    return httpRequest;
  }
  window.createXMLHttpRequest = createXMLHttpRequest;
})();

将创建核心对象的代码写入某个js文件后,我们在html文件中进行引用并初始化核心对象,将其打印。

image-20200829180920024

可以看到我们的核心对象成功的被打印出来了。

二:监听onreadystatechange事件

此事件可以通过核心对象readyState属性获取当前请求内容的状态,因此可以利用此状态来判断异步请求是否完成。

监听很简单,调用核心对象的onreadystatechange方法即可进行监听。

xhr.onreadystatechange = function () {}

监听完事件后还没完,我们首先需要通过核心对象的readyState属性进行判断当前异步提交的状态,其次无论服务器端返回结果是什么(404,服务器错误等),readyState属性最终都会变成4,因此需要通过status属性判断响应码。status属性可以判断响应结果是否成功或者失败。

关于readyState一共有五种状态,

  • 0

    未初始化

  • 1

    open()方法被调用

  • 2

    send()方法被调用

  • 3

    正在相应

  • 4

    相应完毕

而响应码指的是网络请求返回的状态码,通常有200,301,404,502等状态码。其中200表示请求成功,也就是我们需要判断的条件。

因此我们监听事件即可改为如下代码:

xhr.onreadystatechange = function () {
    if (xhr.status === 200 && xhr.readyState === 4) {
        // 当请求成功时执行的代码
    }
}

三:设置请求方式及地址

设置请求方式及地址用到的是核心对象的open方法。此方法共有四种传参形式。

xhr.open(method, url)
xhrReq.open(method, url, async);
xhrReq.open(method, url, async, user);
xhrReq.open(method, url, async, user, password);

但通常我们只会用第一种,其他三种可以参考MDN

这里我们以一言接口为例,演示GET请求。所以我们的open传递两个参数。

xhr.open('get', 'https://v1.hitokoto.cn/')

四:设置发送的数据

发送数据使用send()方法即可。其中传入的参数为需要发送的数据。但是并非所有方式都需要传入数据。

  • 请求方式为GET

    传入参数一定为null,而不是与将数据当作参数传入

  • 请求方式POST

    传入参数为需要提交的参数。格式为key=value&key=value.传参格式可以通过setRequestHeader属性进行修改。

    例如xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")

因为一言的接口请求是通过GET方式获取的,因此我们传送的参数为null

xhr.send(null)

五:处理数据

接下来只需要在第二步中在当请求成功时执行的代码部分进行编写处理代码。但是遇到一个问题,如何获得返回结果?通过核心对象responseText属性可以获取响应的内容。

  1. 先来打印下返回结果

    xhr.onreadystatechange = function () {
        if (xhr.status === 200 && xhr.readyState === 4) {
            // 当请求成功时执行的代码
            console.log(xhr.responseText);
        }
    }
    

    image-20200829215812773

  2. 处理数据

    很明显数据是一个字符串格式,那么为了方便处理,我们需要将他转换为JSON对象。

    xhr.onreadystatechange = function () {
        if (xhr.status === 200 && xhr.readyState === 4) {
            // 当请求成功时执行的代码
            var text = JSON.parse(xhr.responseText)
            console.log(text);
        }
    }
    

    image-20200829220108041

    可以看到,刚刚的数据已经变成了一个js的对象。我们只需要将这个对象取出来,进行处理即可。

    xhr.onreadystatechange = function () {
        if (xhr.status === 200 && xhr.readyState === 4) {
            // 当请求成功时执行的代码
            var text = JSON.parse(xhr.responseText)
            document.querySelector('p').textContent = text.hitokoto
        }
    }
    

    接下来页面中就显示了我们的一言。但是只有当刷新页面时才会更新一言,因此我们需要在做一个按钮,用来获取一言。

示例代码

在线地址:[https://tzk.acs.pw](https://tzk.acs.pw/2020-08/29/code/4. JS_ajax.html)

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="createXMLHttpRequestObject.js"></script>
    </head>

    <body>
        <button id="btn">点击获取</button>
        <p></p>
        <script>
            var btn = document.getElementById('btn')
            btn.addEventListener('click', function () {
                // 1. 创建核心对象
                var xhr = new createXMLHttpRequest()
                // 2. 监听异步请求状态
                xhr.onreadystatechange = function () {
                    if (xhr.status === 200 && xhr.readyState === 4) {
                        // 当请求成功时执行的代码
                        var text = JSON.parse(xhr.responseText)
                        document.querySelector('p').textContent = text.hitokoto
                    }
                }
                // 设置请求方式及地址
                xhr.open('get', 'https://v1.hitokoto.cn/')
                // 设置发送数据
                xhr.send(null)
            })

        </script>
    </body>

</html>
原生JavaScript中,由于同源策略(Same-Origin Policy)的限制,直接的Ajax请求默认情况下不允许。但是,你可以通过以下几种方式实现请求: 1. JSONP (JSON with Padding):这是一种利用script标签的src属性可以加载资源的特性。服务器返回一个经过特殊处理的脚本,通常是一个`<script>`标签,其中包含了数据作为查询字符串的一部分。 ```javascript function jsonp(url, callbackParam, callback) { var script = document.createElement('script'); script.src = url + '?callback=' + callbackParam; window[callbackParam] = function(data) { script.parentNode.removeChild(script); callback && callback(data); }; document.head.appendChild(script); } ``` 2. CORS (Cross-Origin Resource Sharing):服务器端需要设置响应头`Access-Control-Allow-Origin`允许特定来源访问。客户端则需设置`withCredentials`属性来启用认证,如支持XMLHttpRequest 2.0版本。 ```javascript var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://api.example.com/data', true); xhr.withCredentials = true; xhr.onload = function() { if (xhr.status === 200) { console.log(xhr.responseText); } }; xhr.send(); ``` 3. 代理服务器:如果你有对后端的控制权,可以在服务器上设置一个代理,前端发送请求到这个代理,代理再转发到目标服务,这样就绕过了浏览器的同源策略。 请注意,以上方法都需要服务器配合才能成功,如果服务器不允许,上述方式将无法生效。此外,JSONP的安全性较差,因为它依赖于全局变量,不适合敏感信息的传输。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值