精通jQuery AJAX:异步请求完全指南

本文深入探讨jQuery的$.ajax()函数,涵盖其配置选项、实际应用场景如实时搜索功能、安全最佳实践、错误调试技巧、性能优化方法以及现代替代方案,帮助开发者全面掌握异步HTTP请求技术。

精通jQuery AJAX:异步请求完全指南

Ajax是一种技术,允许开发者向服务器发出异步HTTP请求,以检索或发送数据,而无需完全刷新页面。长期以来,开发者一直使用jQuery来简化这一过程,使其比纯JavaScript更便捷。

在我之前的文章《jQuery简写Ajax方法介绍》中,我讨论了jQuery中最常用的一些Ajax调用,包括$.get()$.post()$.load(),这些方法只需几行代码即可在jQuery中方便地进行Ajax请求。但有时我们需要对Ajax调用进行更多控制。例如,我们需要指定Ajax请求失败时应执行的操作,或者需要执行Ajax调用函数,但仅在一定时间内获取结果时才需要其结果。在这种情况下,我们可以依赖jQuery中Ajax提供的另一个函数$.ajax(),这是本教程的主题。

关键要点

  • 多功能性和控制:jQuery $.ajax()函数提供了一种灵活而强大的方式来进行异步HTTP请求,允许开发者广泛控制请求和响应过程。它支持多种设置,如指定成功和错误的回调函数、设置请求头、处理数据类型以及为HTTP访问认证请求添加认证令牌,这使其能够适应各种场景,超出了简写Ajax调用函数如$.get()$.post()$.load()的能力范围。
  • 全面的配置选项:文章重点介绍了$.ajax()可用的全面配置选项列表,这些选项可以满足进行Ajax调用时可能遇到的几乎所有需求。从修改请求头到处理响应数据,从处理错误到设置跨域请求,$.ajax()为开发者提供了必要的工具,以微调其Ajax请求和响应,精确满足应用程序的需求。
  • 在现代开发中的相关性:尽管出现了如Fetch等新API,jQuery $.ajax()函数在Web开发中仍然是一个相关且有价值的工具,特别是在维护遗留代码库或对于偏好jQuery提供的简单性和一致性的开发者来说。其易用性结合功能的深度,确保$.ajax()在需要Ajax调用的项目中仍能发挥关键作用,突显了jQuery在Web开发生态系统中的持续效用。
  • 高级错误处理和重试策略:通过使用指数退避的重试机制演示了强大的错误处理,确保应用程序能够优雅地从临时网络或服务器故障中恢复。开发者还可以定义全局错误处理程序来调试和跟踪多个请求中的错误。

$.ajax()函数

jQuery $.ajax()函数用于执行异步HTTP请求。它很久以前就被添加到库中,自版本1.0以来一直存在。$.ajax()函数是$.get()$.post()$.load()在幕后使用预设配置进行调用的基础。该函数的签名如下所示:

1
2
$.ajax(url[, settings])
$.ajax([settings])

Ajax参数中的URL是一个字符串,包含您希望通过jQuery Ajax调用访问的Ajax URL,而settings是一个对象字面量,包含Ajax请求的配置。

在其第一种形式中,此函数使用URL参数和settings中指定的选项执行Ajax请求。在第二种形式中,URL在settings参数中指定或可以省略,在这种情况下,请求将发送到当前页面。

此函数接受的选项列表非常长,因此我将保持其描述简短。如果您想深入研究它们的含义,可以参考$.ajax()的官方文档。

Settings参数

您可以指定许多不同的选项来使$.ajax()适应您的需求。在下表中,您可以按字母顺序找到它们的名称和描述:

参数 默认值 可能值 描述和用例
accepts { “”: “/*” } 任何MIME类型字符串 在请求头中发送的内容类型,告诉服务器它将接受何种类型的响应。
beforeSend 函数 一个预请求回调函数,可用于在发送jqXHR对象之前修改它。
cache true(脚本除外) true或false 将此选项设置为false以强制请求的页面不被浏览器缓存。
complete 函数 请求完成时调用的函数(在成功和错误回调执行之后)。
contentType “application/x-www-form-urlencoded; charset=UTF-8” MIME类型字符串 发送到服务器的数据的内容类型。
context window 任何对象 用作所有Ajax相关回调的上下文(this)的对象。
converters 取决于dataType 对象映射 包含数据类型到数据类型转换器的对象。
crossDomain false true或false 将此属性设置为true以在同一域上强制跨域请求。
data 对象、字符串或数组 执行Ajax请求时发送到服务器的数据。
dataFilter 函数 用于处理XMLHttpRequest原始响应数据的函数。
dataType text xml、html、json、text等 从服务器期望返回的数据类型。避免使用jsonp请求,因为它已基本过时。
error 函数 请求失败时调用的函数。
global true true或false 是否为此请求触发全局Ajax事件处理程序。
headers 对象 要发送到服务器的附加头对象。
ifModified false true或false 仅当响应自上次请求以来已更改时才处理响应。
isLocal 取决于环境 true或false 强制jQuery将当前环境视为本地环境。
mimeType MIME类型字符串 指定mime类型的字符串,以覆盖XHR mime类型。
password 字符串 用于XMLHttpRequest的密码,以响应HTTP访问认证请求。
processData true true或false 确定是否应自动将数据序列化为查询字符串。
scriptCharset 字符串 设置请求中使用的脚本标签的charset属性,但仅在使用“脚本”传输时适用。
statusCode 对象 将HTTP状态码映射到回调函数。
success 函数 请求成功时调用的函数。
timeout 0(无超时) 整数 指定请求超时(毫秒)的数字。
type “GET” “GET”、“POST”等 要发出的请求类型。
url 当前页面URL 字符串 包含请求发送到的URL的字符串。
username 字符串 用于XMLHttpRequest的用户名,以响应HTTP访问认证请求。
xhr 函数 用于创建XMLHttpRequest对象的回调函数。
xhrFields 对象 设置在本地XHR对象上的对象。

这是一个相当长的列表,不是吗?好吧,作为开发者,您可能在第5或第6个元素时就停止阅读这个列表了,我想,但这没关系。下一节将更加令人兴奋,因为我们将把$.ajax()函数和一些这些选项付诸实践。

付诸实践

在本节中,我们将详细讨论$.ajax()函数及其一些选项的实际应用。

$.ajax()的第一个示例

我们将从一个简单的演示开始,重现我们在上一篇文章中开发的相同代码。作为回顾,我们将假设我们的网站中有一个ID为main的元素,代表主要内容。我们想要做的是异步从主菜单中链接引用的页面加载数据,主菜单的理想ID为main menu。我们只想检索此元素内的内容,因为布局的其他部分不会改变,因此不需要加载。

这种方法旨在作为一种增强,因为如果访问网站的用户禁用了JavaScript,他们仍然可以使用通常的同步机制浏览网站。在此示例中,我们假设菜单中的所有链接都是内部链接。

我们将从一个简单的演示开始,重现我们在上一篇文章中开发的相同代码,但这次我们将采用$.ajax()。为方便起见,下面显示了我们之前开发的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$('#main-menu a').on('click', function(event) {
  event.preventDefault();

  $('#main').load(this.href + ' #main *', function(responseText, status) {
  if (status === 'success') {
    $('#notification-bar').text('The page has been successfully loaded');
  } else {
      $('#notification-bar').text('An error occurred');
    }
  });
});

更新此代码片段以使用$.ajax()函数,我们得到以下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$('#main-menu a').on('click', function(event) {
  event.preventDefault();

  $.ajax(this.href, {
    success: function(data) {
      $('#main').html($(data).find('#main *'));
      $('#notification-bar').text('The page has been successfully loaded');
},
    error: function() {
      $('#notification-bar').text('An error occurred');
    }
  });
});

在这里,您可以看到我使用了函数的第一种形式。我将URL指定为第一个参数,然后将settings对象作为第二个参数。后者利用了上一节讨论的几个属性中的两个——success和error——分别指定在请求成功或失败时应执行的操作。

添加自定义头和处理HTTP访问认证请求

Image Source

在第二个示例中,我们将探索如何通过添加自定义头、处理认证令牌以及与需要特定安全措施的API交互来增强您的AJAX请求。这些是与现代Web应用程序通信外部API时的常见场景。

假设您正在与一个需要令牌进行HTTP访问认证请求的API交互。您可以使用$.ajax()中的headers选项将此令牌作为请求头的一部分包含:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$('#main-menu a').on('click', function(event) {
  event.preventDefault();

  $.ajax({
    url: this.href,
    headers: {
      "Authorization": "Bearer YOUR_TOKEN_HERE",
      "X-Custom-Header": "CustomValue"
    },
    success: function(data) {
      $('#main').html($(data).find('#main *'));
      $('#notification-bar').text('The page has been successfully loaded with custom headers');
    },
    error: function() {
      $('#notification-bar').text('An error occurred while loading the page with custom headers');
    }
  });
});

在此示例中,Authorization头包含一个承载令牌,通常用于安全地与API认证请求。此外,X-Custom-Header作为额外的元数据头,通常由专有API要求以提供额外上下文或符合特定服务器要求。

添加自定义头在与安全API合作时特别有用,确保适当的认证并向服务器提供任何必要的上下文信息。

使用$.ajax()管理复杂数据结构

API通常需要结构化数据,如嵌套JSON对象,以处理过滤器或分层信息。以下示例演示了如何使用$.ajax()函数的data属性发送结构化数据:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$.ajax({
  url: '/api/products',
  headers: {
     "Authorization": "Bearer YOUR_TOKEN_HERE",
     "X-Custom-Header": "CustomValue"
  },
  type: 'POST',
  contentType: 'application/json', // 指定JSON格式
  data: JSON.stringify({
    category: 'electronics',
    filters: {
      brand: 'Samsung',
      priceRange: [100, 500]
    }
  }),
  success: function(data) {
      $('#main').html($(data).find('#main *'));
      $('#notification-bar').text('The data has been sent successfully');
    },
    error: function() {
      $('#notification-bar').text('An error occurred while sending data');
    }
});

这里,contentType: 'application/json'指定了发送的数据格式,JSON.stringify()将JavaScript对象转换为JSON字符串,以便与API兼容。这对于需要复杂查询或分层过滤器的API来说是理想的。

实际应用场景:实时搜索功能

既然您了解了$.ajax()的工作原理,让我们来看一个实际场景,其中$.ajax()非常有用。例如,假设您正在构建一个在线商店,并且希望用户在搜索框中输入时动态搜索产品。而不是每次重新加载整个页面,搜索结果应立即出现,为用户提供流畅和交互式的体验。

工作原理

当用户在搜索框中输入时,他们的查询字符串通过AJAX请求发送到服务器。服务器处理查询字符串并返回匹配的产品,这些产品立即显示在页面上。这保持了体验的快速和无缝。

以下是您可以处理的方式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$('#search-box').on('input', function() {
  let query = $(this).val().trim();

  if (query.length > 2) { // 仅对有意义的输入进行搜索
    $.ajax({
      url: "/search-products",
      type: "GET",
      data: { query: query },
      success: function(response) {
        let results = response.products.map(product => `
          <div class="product">
            <h3>${product.name}</h3>
            <p>${product.description}</p>
            <span>Price: $${product.price}</span>
          </div>
        `).join('');
        $('#search-results').html(results); // 动态显示结果
      },
      error: function() {
        $('#search-results').html('<p>Unable to load results. Please try again.</p>');
      }
    });
  } else {
    $('#search-results').empty(); // 清除短查询的结果
  }
});

为什么这很重要

想想用户在不重新加载页面查看搜索结果时节省了多少时间。这种方法:

  • 增强可用性:结果实时出现,使界面感觉更响应。
  • 节省带宽:仅获取所需数据,减少服务器上的不必要负载。
  • 改善用户体验:更快、更流畅的交互使用户保持参与。

通过应用这种简单模式,您可以将基本搜索框转换为动态、用户友好的功能,提升您的Web应用程序。

安全可靠AJAX请求的最佳实践

为确保您的AJAX请求安全可靠,遵循解决常见安全问题和优化开发过程的最佳实践非常重要。

错误处理策略

  • 使用错误回调函数或全局处理程序实施强大的错误处理,以向用户提供有意义的反馈并优雅地处理重试。
  • 避免无限重试以防止服务器过载;相反,实施如指数退避等策略。

跨域请求和安全考虑

Image Source

  • 使用跨域资源共享(CORS)安全地处理跨域请求。确保服务器明确允许来自受信任源的请求。
  • 通过转义或清理输入和输出来防止跨站脚本(XSS)攻击。使用如DOMPurify等工具在处理用户输入之前进行清理。
  • 在客户端和服务器端验证所有用户输入,以确保仅处理预期数据。
  • 始终通过HTTPS传输敏感数据,以保护传输中的数据并防止窃听或中间人攻击。

提高AJAX安全性

  • 使用如DOMPurify等库清理用户输入并防止XSS攻击。let cleanInput = DOMPurify.sanitize(userInput);
  • 使用如Content-Security-Policy(CSP)等HTTP头来缓解注入攻击。
  • 实施反CSRF令牌以防止跨站请求伪造攻击。$.ajax({ url: '/secure-endpoint', type: 'POST', headers: { 'X-CSRF-Token': csrfToken }, data: { input: cleanInput } });
  • 通过将敏感API密钥安全地存储在服务器端来避免在前端暴露它们。
  • 定期审计和更新您的依赖项,包括jQuery,以解决已知漏洞。

调试Ajax请求:请求失败时该怎么办

调试Ajax jQuery请求有时可能很棘手,因为它们的异步性质以及涉及客户端和服务器端代码。以下是一些有效的技巧,用于调试与jQuery $.ajax()方法相关的问题:

  1. 使用浏览器开发者工具

    • 网络标签:检查浏览器开发者工具中的网络标签以检查Ajax请求。验证请求URL、头、负载和响应。查找任何错误或意外状态码。
    • 控制台标签:在控制台标签中查找JavaScript错误或警告,这些可能指示您的jQuery Ajax调用或其回调函数存在问题。
  2. 检查服务器端日志

    • 如果jQuery Ajax调用到达服务器但行为不符合预期,检查服务器端日志以查找错误或警告。这可以提供有关服务器端代码或配置问题的线索。
  3. 记录请求和响应

    • 临时在$.ajax()调用的success、error和complete回调中添加console.log()语句,以记录响应或任何错误消息。这可以帮助您了解服务器返回的内容或请求失败的原因。
  4. 验证数据类型

    • 确保您的$.ajax()调用中的dataType选项与服务器返回的实际数据类型匹配。此处的不匹配可能导致jQuery错误处理响应,从而引发意外行为。
  5. 单独测试API端点

    • 使用如Postman或curl等工具手动测试API端点。这可以帮助您验证API是否正常工作,并了解预期的请求格式和响应数据。
  6. 验证JSON响应

    • 对于JSON数据,使用在线JSON验证器或调试工具验证响应,以确保其格式正确。格式错误的JSON可能导致解析错误。
  7. 使用jQuery.ajaxError()进行全局错误处理

    • 在文档上绑定事件处理程序到ajaxError,以全局捕获和处理Ajax请求错误。这可以帮助您识别和调试应用程序中失败的Ajax请求。
1
2
3
$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
    console.error("AJAX Request Failed: ", settings.url, thrownError);
});
  1. 简化和隔离
    • 简化您的$.ajax()调用或将其隔离在简单环境/页面中,以验证其行为而不受其他脚本或Ajax调用的干扰。

有时,这些错误可能是由于网络问题而暂时的。实施具有递增延迟的重试(指数退避)可以自动处理这种情况,并提高应用程序的可靠性。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
function ajaxWithRetry(url, retries, delay) {
  $.ajax({
    url: url,
    success: function(data) {
      console.log('Success:', data);
    },
    error: function() {
      if (retries > 0) {
        setTimeout(() => {
          ajaxWithRetry(url, retries - 1, delay * 2);
        }, delay);
      } else {
        console.error('Failed after retries');
      }
    }
  });
}
ajaxWithRetry('/fetch-data', 3, 1000);

该函数最多重试请求3次,每次失败后延迟加倍。这有助于处理网络故障或临时服务器不可用。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计