JavaScript异步Ajax技术详解:从原理到实战

作者:函数茶馆

时间:2026-10-25

浏览:377

本文详细解析JavaScript中Ajax技术的实现原理,涵盖XMLHttpRequest对象的创建、GET与POST请求的区别、异步处理机制以及响应状态码的监听。通过具体代码示例,指导开发者如何在现代浏览器及旧版IE中正确发送和处理服务器数据,实现网页的局部无刷新更新。

文章目录

一、什么是 AJAX ?

AJAX 全称为异步 JavaScript 和 XML。这是一种用于构建快速动态网页的技术方案。

AJAX 允许网页在后台与服务器进行少量数据交换,从而实现网页的异步更新。这意味着用户可以在不重新加载整个页面的情况下,仅更新页面的部分内容。相比之下,传统网页在需要更新内容时,必须重新加载整个页面。

市面上有许多应用 AJAX 技术的典型案例,例如新浪微博、Google 地图以及开心网等。

1、AJAX是基于现有的Internet标准

AJAX 建立在现有的 Internet 标准之上,并综合运用了以下技术:

  • XMLHttpRequest 对象(用于与服务器异步交换数据)
  • JavaScript/DOM(用于信息的显示与交互)
  • CSS(用于为数据定义样式)
  • XML(用于作为数据传输的格式)

需要注意的是,AJAX 应用程序与具体的浏览器及平台无关。

2、AJAX 工作原理

一、什么是 AJAX ?

二、AJAX - 创建 XMLHttpRequest 对象

1、XMLHttpRequest 对象

XMLHttpRequest 是 AJAX 技术的核心基础。所有现代浏览器均原生支持 XMLHttpRequest 对象,而在 IE5 和 IE6 中则需使用 ActiveXObject。

XMLHttpRequest 的主要作用是在后台与服务器交换数据,从而实现在不重新加载整个网页的前提下,对网页的特定部分进行更新。

2、创建 XMLHttpRequest 对象

所有现代浏览器(包括 IE7 及以上版本、Firefox、Chrome、Safari 以及 Opera)均内置了 XMLHttpRequest 对象。

创建 XMLHttpRequest 对象的标准语法如下:

variable=new XMLHttpRequest();

对于老版本的 Internet Explorer(即 IE5 和 IE6),则需使用 ActiveX 对象:

variable=new ActiveXObject("Microsoft.XMLHTTP");

为了确保代码兼容所有现代浏览器,包括 IE5 和 IE6,建议先检查浏览器是否支持 XMLHttpRequest 对象。如果支持,则创建 XMLHttpRequest 对象;如果不支持,则创建 ActiveXObject:

var xmlhttp;
if (window.XMLHttpRequest)
{
    //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
    xmlhttp=new XMLHttpRequest();
}
else
{
    // IE6, IE5 浏览器执行代码
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}

三、向服务器发送请求请求

1、向服务器发送请求

XMLHttpRequest 对象用于与服务器进行数据交换。

若要将请求发送至服务器,需使用 XMLHttpRequest 对象的 open() 和 send() 方法:

xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();

相关方法说明:

open(method,url,async):用于规定请求的类型、URL 地址以及是否采用异步方式处理请求。

  • method:指定请求的类型,可选 GET 或 POST。
  • url:指定服务器端文件的位置。
  • async:指定是否异步处理,true 表示异步,false 表示同步。

send(string):将请求发送至服务器。其中 string 参数仅在使用 POST 请求时有效。

注意:open() 方法中的 url 参数指向的是服务器端文件的地址:

xmlhttp.open("GET","ajax_test.html",true);

该文件可以是任何类型,例如 .txt 或 .xml,也可以是服务器脚本文件,如 .asp 或 .php(在返回响应之前,服务器端可执行相应任务)。

2、GET 还是 POST?

与 POST 请求相比,GET 请求更为简单且速度更快,且在大多数场景下均可使用。

然而,在以下情况中,建议使用 POST 请求:

  • 无法使用缓存文件(例如需要更新服务器上的文件或数据库)。
  • 向服务器发送大量数据(POST 请求没有数据量限制)。
  • 发送包含未知字符的用户输入时,POST 比 GET 更稳定且更可靠。

3、GET 请求

一个简单的 GET 请求示例如下:

xmlhttp.open("GET","/try/ajax/demo_get.php",true);
xmlhttp.send();

在上述示例中,浏览器可能会返回缓存的结果。

为避免这种情况,可向 URL 中添加一个唯一的 ID:

xmlhttp.open("GET","/try/ajax/demo_get.php?t=" + Math.random(),true);
xmlhttp.send();

如果希望使用 GET 方法发送额外信息,可将信息附加到 URL 中:

xmlhttp.open("GET","/try/ajax/demo_get2.php?fname=Henry&lname=Ford",true);
xmlhttp.send();

4、POST 请求

一个简单的 POST 请求示例如下:

xmlhttp.open("POST","/try/ajax/demo_post.php",true);
xmlhttp.send();

若需像 HTML 表单那样发送 POST 数据,请使用 setRequestHeader() 方法添加 HTTP 头部信息。随后在 send() 方法中指定希望发送的数据:

xmlhttp.open("POST","/try/ajax/demo_post2.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Henry&lname=Ford");

5、异步 - True 或 False?

AJAX 全称为异步 JavaScript 和 XML(Asynchronous JavaScript and XML)。

若 XMLHttpRequest 对象用于 AJAX,其 open() 方法中的 async 参数必须设置为 true:

xmlhttp.open("GET","ajax_test.html",true);

对于 Web 开发人员而言,发送异步请求是一项巨大的进步。许多在服务器端执行的任务耗时较长,而在 AJAX 出现之前,这可能导致应用程序挂起或停止响应。

通过 AJAX,JavaScript 无需等待服务器响应,而是可以:

  • 在等待服务器响应时执行其他脚本。
  • 当响应就绪后,对响应进行处理。

当使用 async=true 时,需规定在响应处于 onreadystatechange 事件中的就绪状态时执行的函数:

xmlhttp.onreadystatechange=function()
{
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
        document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
}
xmlhttp.open("GET","/try/ajax/ajax_info.txt",true);
xmlhttp.send();

注意:当使用 async=false 时,请勿编写 onreadystatechange 函数,而应将代码放置在 send() 语句之后即可:

xmlhttp.open("GET","/try/ajax/ajax_info.txt",false);
xmlhttp.send();
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;

四、AJAX - 服务器 响应

如需获取来自服务器的响应,请使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性。

  • responseText:获取字符串形式的响应数据。
  • responseXML:获取 XML 形式的响应数据。

1、responseText 属性

如果来自服务器的响应并非 XML 格式,请使用 responseText 属性。

responseText 属性返回字符串形式的响应,因此您可以按以下方式使用:

document.getElementById("myDiv").innerHTML=xmlhttp.responseText;

2、responseXML 属性

如果来自服务器的响应是 XML,且需要作为 XML 对象进行解析,请使用 responseXML 属性:

xmlDoc=xmlhttp.responseXML;
txt="";
x=xmlDoc.getElementsByTagName("ARTIST");
for (i=0;i<x.length;i++)
{
    txt=txt + x[i].childNodes[0].nodeValue + "<br>";
}
document.getElementById("myDiv").innerHTML=txt;

五、AJAX - onreadystatechange 事件

当请求被发送到服务器时,我们需要根据响应执行相应的任务。

每当 readyState 属性发生变化时,就会触发 onreadystatechange 事件。

readyState 属性保存了 XMLHttpRequest 的状态信息。

1、XMLHttpRequest 对象的三个重要的属性:

1、onreadystatechange:存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。

2、readyState:保存 XMLHttpRequest 的状态,取值从 0 到 4 发生变化。

  • 0: 请求未初始化
  • 1: 服务器连接已建立
  • 2: 请求已接收
  • 3: 请求处理中
  • 4: 请求已完成,且响应已就绪

3、status:状态码。200 表示 "OK";404 表示未找到页面。

在 onreadystatechange 事件中,我们规定当服务器响应已做好被处理准备时所执行的任务。

当 readyState 等于 4 且状态为 200 时,表示响应已就绪:

xmlhttp.onreadystatechange=function()
{
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
        document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
}

注意:onreadystatechange 事件会被触发 4 次(状态码从 0 到 4),分别对应:0-1、1-2、2-3、3-4,即 readyState 的每次变化。

2、使用回调函数

回调函数是一种以参数形式传递给另一个函数的函数。

如果您的网站上存在多个 AJAX 任务,建议编写一个标准的函数来创建 XMLHttpRequest 对象,并为每个 AJAX 任务调用该函数。

该函数调用应包含 URL 以及发生 onreadystatechange 事件时执行的任务(每次调用可能不尽相同):

function myFunction()
{
    loadXMLDoc("/try/ajax/ajax_info.txt",function()
    {
        if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
            document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
        }
    });
}

六、javascript 脚本化的HTTP----ajax的基石

1、建XMLHttpRequest对象

// This is a list of XMLHttpRequest-creation factory functions to try
HTTP._factories = [
    function() { return new XMLHttpRequest(); },
    function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
    function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];

// When we find a factory that works, store it here.
HTTP._factory = null;

// Create and return a new XMLHttpRequest object.
//
// The first time we're called, try the list of factory functions until
// we find one that returns a non-null value and does not throw an
// exception. Once we find a working factory, remember it for later use.
//
HTTP.newRequest = function() {
    if (HTTP._factory != null) return HTTP._factory();

    for(var i = 0; i < HTTP._factories.length; i++) {
        try {
            var factory = HTTP._factories[i];
            var request = factory();
            if (request != null) {
                HTTP._factory = factory;
                return request;
            }
        }
        catch(e) {
            continue;
        }
    }
    // If we get here, none of the factory candidates succeeded,
    // so throw an exception now and for all future calls.
    HTTP._factory
 = function() {
        throw new Error("XMLHttpRequest not supported");
    }
    HTTP._factory(); // Throw an error
}

2、Get请求

HTTP.get = function(url, callback, options) {
    var request = HTTP.newRequest();
    var n = 0;
    var timer;
    if (options.timeout)
        timer = setTimeout(function() {
                               request.abort();
                               if (options.timeoutHandler)
                                   options.timeoutHandler(url);
                           },
                           options.timeout);

    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            if (timer) clearTimeout(timer);
            if (request.status == 200) {
                callback(HTTP._getResponse(request));
            }
            else {
                if (options.errorHandler)
                    options.errorHandler(request.status,
                                         request.statusText);
                else callback(null);
            }
        }
        else if (options.progressHandler) {
            options.progressHandler(++n);
        }
    }

    var target = url;
    if (options.parameters)
        target += "?" + HTTP.encodeFormData(options.parameters)
    request.open("GET", target);
    request.send(null);
};

1、GET工具

//getText()工具
HTTP.getText = function(url, callback) {
var request = HTTP.newRequest();
request.onreadystatechange = function() {
if(request.readyState == 4 && request.status == 200) {
callback(request.responseText);
}
}


request.open("GET", url);
request.send(null);
}


//getXML()工具
HTTP.getXML = function(url, callback) {
var request = HTTP.newRequest();
request.onreadystatechange = function() {
if(request.readyState == 4 && request.status == 200) {
callback(request.responseXML);
}
}


request.open("GET", url);
request.send(null);
}

3、POST请求

/**
 * Send an HTTP POST request to the specified URL, using the names and values
 * of the properties of the values object as the body of the request.
 * Parse the server's response according to its content type and pass
 * the resulting value to the callback function. If an HTTP error occurs,
 * call the specified errorHandler function, or pass null to the callback
 * if no error handler is specified.
 **/
HTTP.post = function(url, values, callback, errorHandler) {
    var request = HTTP.newRequest();
    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            if (request.status == 200) {
                callback(HTTP._getResponse(request));
            }
            else {
                if (errorHandler) errorHandler(request.status,
                                               request.statusText);
                else callback(null);
            }
        }
    }

    request.open("POST", url);
    // This header tells the server how to interpret the body of the request.
    request.setRequestHeader("Content-Type",
                             "application/x-www-form-urlencoded");
    // Encode the properties of the values object and send them as
    // the body of the request.
    request.send(HTTP.encodeFormData(values));
};

4、获取Http头(包括解析头部数据)

HTTP.getHeaders = function(url, callback, errorHandler) {
    var request = HTTP.newRequest();
    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            if (request.status == 200) {
                callback(HTTP.parseHeaders(request));
            }
            else {
                if (errorHandler) errorHandler(request.status,
                                               request.statusText);
                else callback(null);
            }
        }
    }
    request.open("HEAD", url);
    request.send(null);
};

// Parse the response headers from an XMLHttpRequest object and return
// the header names and values as property names and values of a new object.
HTTP.parseHeaders = function(request) {
    var headerText = request.getAllResponseHeaders();  // Text from the server
    var headers = {}; // This will be our return value
    var ls = /^"s*/;  // Leading space regular expression
    var ts = /"s*$/;  // Trailing space regular expression

    // Break the headers into lines
    var lines = headerText.split(""n");
    // Loop through the lines
    for(var i = 0; i < lines.length; i++) {
        var line = lines[i];
        if (line.length == 0) continue;  // Skip empty lines
        // Split each line at first colon, and trim whitespace away
        var pos = line.indexOf(':');
        var name = line.substring(0, pos).replace(ls, "").replace(ts, "");
        var value = line.substring(pos+1).replace(ls, "").replace(ts, "");
        // Store the header name/value pair in a JavaScript object
        headers[name] = value;
    }
    return headers;
};

5、私有方法

1、获取表单数据:

/**
 * Encode the property name/value pairs of an object as if they were from
 * an HTML form, using application/x-www-form-urlencoded format
 */
HTTP.encodeFormData = function(data) {
    var pairs = [];
    var regexp = /%20/g; // A regular expression to match an encoded space

    for(var name in data) {
        var value = data[name].toString();
        // Create a name/value pair, but encode name and value first
        // The global function encodeURIComponent does almost what we want,
        // but it encodes spaces as %20 instead of as "+". We have to
        // fix that with String.replace()
        var pair = encodeURIComponent(name).replace(regexp,"+") + '=' +
            encodeURIComponent(value).replace(regexp,"+");
        pairs.push(pair);
    }

    // Concatenate all the name/value pairs, separating them with &
    return pairs.join('&');
};

2、获取响应:

HTTP._getResponse = function(request) {
switch(request.getResponseHeader("Content-Type")) {
case "text/xml":
return request.responseXML;

case "text/json":
case "text/javascript":
case "application/javascript":
case "application/x-javascript":
return eval(request.responseText);

default:
return request.responseText;
}
}

6、使用:

//提交表单,调用POST方法
var uname = document.getElementById("username");
var usex = document.getElementById("sex");
var formdata = {'username':'tom','sex':'男'};
    HTTP.post("./test.php",formdata, doFun, errorFun);
//请求获取指定的URL的headers
 HTTP.getHeaders("./a.html", doFun, errorFun);

到此这篇关于JavaScript实现异步Ajax的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章