详解JavaScript中jQuery和Ajax以及JSONP的联合使用


Posted in Javascript onAugust 13, 2015

借助于 XMLHttpRequest,浏览器可以在整个页面不刷新的情况下与服务端进行交互,这就是所谓的 Ajax(Asynchronous JavaScript and XML)。Ajax 可以为用户提供更为丰富的用户体验。

Ajax 请求由 JavaScript 驱动,通过 JavaScript 代码向 URL 发送一个请求,待服务端有响应时会触发一个回调函数,可以在这里回调函数里面处理服务端返回的信息。由于整个发送请求和响应的过程是异步的,所以在此期间页面中其它 Javascript 代码仍然继续执行,不会中断。

jQuery 对 Ajax 当然也提供了很好的支持,而且还抽象了各种浏览器对于 Ajax 支持方面另人痛苦的差异。它不但提供了全功能的 $.ajax() 方法,还有诸如 $.get(),$.getScript(),$.getJSON(),$.post() 和 $().load() 等更为简便的方法。

尽管被命名为 Ajax,但是很多 Ajax 应用并没有使用 XML,特别是 jQuery 方面的 Ajax 应用,大多数都没有使用 XML;反而用得比较多的情况是:纯文本、HTML 以及 JSON(JavaScript Object Notation)。

一般情况下,由于同源策略(同协议,同域名,同端口)的限制,Ajax 并不能跨域执行请求,除非使用诸如 JSONP(JSON with Padding) 之类的方案,才能实现一些受限的跨域功能。
关于 Ajax 的一些重要概念

GET vs POST,这是两种最常用的向服务端发送请求的方法,正确理解这两种方法的区别对于 Ajax 开发非常重要。

GET 方法通常用于执行一些非破坏性的操作(就是说,只从服务端获取信息,不修改服务端上的信息)。例如,搜索查询服务一般会使用 GET 请求。另外,GET 请求还可能会被浏览器缓存,这可能会导致一些不可预知的问题。一般情况下 GET 请求只能通过查询字符串的方式向服务端发送数据。

POST 方法通常用于在服务端上执行一些破坏性的操作(就是说,会修改服务端上的数据)。例如,当你发表一篇博客的时候,用的应该就是 POST 请求。和 GET 请求不一样,POST 请求不存在缓存问题。POST 请求中,查询字符串作为 URL 的一部分也能向服务端提交数据,但不推荐这种方法,所有数据应该跟 URL 分开单独发送。

数据类型,jQuery 通常要求指明服务端返回的数据类型,某些情况写数据类型可能已经包含在方法名称中了,如 $.getJSON(),除此之外,它都会被作为一个可配置的对象的一部分,该对象最终会作为 $.ajax() 方法的参数。数据类型通常有以下几种:

  •     text :纯文本,用于传输简单的字符串。
  •     html :用于传输一段 HTML。
  •     script :向页面中添加脚本。
  •     json :传输已格式化的 JSON 对象,它可以包含字符串、数组或对象。
  •     jsonp :用于传输从其他域下返回的 JSON 数据。
  •     xml :用于传输自定义的 XML 格式数据。

异步执行,Ajax 中的 A 指的是异步(Asynchronous)。说到这里可能很多 jQuery 初学者一下子很难理解什么叫异步,因为默认情况下 Ajax 请求就是异步的,服务端返回的信息并非马上就能获取到。所有服务端返回的信息只能在一个回调函数中处理。例如以下这段代码,是错误的:

var response;
$.get('foo.php', function(r) { response = r; });
console.log(response); // undefined!

正确的做法应该是在回调函数中处理服务端返回的数据,回调函数在 Ajax 请求成功完成时才被执行,这个时候才能获取到来自服务端的数据:

$.get('foo.php', function(response) { console.log(response); });

同源策略及 JSONP,前面已经说过,一般情况下 Ajax 的请求会被限制在相同协议(http 或 https)、相同端口、相同域名下才能正确执行,但是 HTML 的 <script> 标签却无此限制,它可以载入任何域下的脚本,jQuery 正是利用了这一点才得以拥有跨域执行 Ajax 的能力。

所谓 JSONP,就是其它域的服务端返回给我们的是 JavaScript 代码,这段代码可以被加载到 HTML 中的 <script> 标签中,这段 JavaScript 代码中包含有从其它域下的服务端返回的 JSON 数据,并以回调函数的形式提供。这样一来 jQuery 就回避了同源策略的限制,曲线拥有了跨域执行 Ajax 的能力。

Ajax 调试工具,现在比较新的浏览器如 Chrome 和 Safari,甚至 IE 都内置了调试工具,Firefox 也有无比强大 FireBug 插件,借助于这些调试工具,可以非常详细的查看 Ajax 的执行过程。
和 Ajax 相关的一些方法

jQuery 提供了好多种简便的 Ajax 方法,但是它们的核心都是 $.ajax,所以必须正确理解 $.ajax。

jQuery 的 $.ajax 是创建 Ajax 请求中最直接也是最有效的方法,它的参数是一个 JavaScript 对象,我们可以在这个对象中对 Ajax 作非常详细的配置。另外,$.ajax 方法还可以分别定义 Ajax 请求成功和失败时的回调函数;而且它以一个可配置的对象作为参数的特性,使得我们可以在 Ajax 方法外配置这个对象,然后再传进来,这非常有助于实现代码复用。关于这个方法的详细文档:http://api.jquery.com/jQuery.ajax/

一个典型的示例如下:

$.ajax({
  // 要请求的 URL
  url : 'post.php',

  // 要发给服务端的数据
  // (将会转化为查询字符串,如:?id=123)
  data : { id : 123 },

  // 定义此 Ajax 请求是 POST 还是 GET
  type : 'GET',

  // 服务端返回的数据类型
  dataType : 'json',

  // Ajax 成功执行时的回调函数;
  // 回调函数的参数即为服务端返回的数据
  success : function(json) {
    $('<h1/>').text(json.title).appendTo('body');
    $('<div class="content"/>')
      .html(json.html).appendTo('body');
  },

  // 如果 Ajax 执行失败;
  // 将返回原始错误信息以及状态码
  // 传入这个回调函数中
  error : function(xhr, status) {
    alert('Sorry, there was a problem!');
  },

  // 这里是无论 Ajax 是否成功执行都会触发的回调函数
  complete : function(xhr, status) {
    alert('The request is complete!');
  }
});

    备注:

    关于 dataType :如果这里定义的 dataType 跟服务端返回的数据格式不一样,我们的代码就可能会执行失败,并且很难查出原因,因为 HTTP 返回的状态码并没有显示出错。所以在执行 Ajax 请求的时候,一定要确保服务端返回的数据格式跟事先定义定义的一致。通常情况下验证 HTTP 头信息中的 Content-type 是行之有效的办法,对于 JSON 而言,对应的 Content-type 应该是 application/json。

$.ajax 的一些自定义选项

$.ajax 方法的自定义选项非常多,这也是此方法功能强大的原因所在。若要查阅所有自定义选项,可参考官方文档:http://api.jquery.com/jQuery.ajax/,下面只列出一些常用的选项:

    async :默认值是 true,如果需要 Ajax 的执行方式为同步,可将其设为 false。请注意,如果把这个值设为 false 了,那么你的其它 JavaScript 代码将会被中断执行,直到此次 Ajax 请求完毕,接受到服务端返回的数据为止才会恢复。所以,请慎用此选项。
    cache :设定是否缓存服务端发回的数据。对于 “script” 和 “jsonp” 之外的其它格式的数据而言,默认值是 true。如果被设置为 false,向服务器发送请求的时候,URL 中会被加入一个查询字符串,字符串的值是当前的时间戳,以确保每次请求的 URL 都是不同的,当然也就不存在缓存问题了。JavaScript 中获取时间戳的方法为 new Date().getTime()。
    complete :Ajax 请求执行完成时触发的回调函数,无论此次执行成功与否,该回调函数都会被触发。该回调函数可以接受服务端返回的原始信息及状态码。
    context :定义回调函数执行时的作用域(回调函数 function(s) {alert(this)} 中的 this 指向谁?)。默认情况下,回调函数中的 this 指向传递给 $.ajax 方法的参数,也就是那个大对象。
    data :要发送给服务端的数据,其值可以是一个对象或者查询字符串,如 foo=bar&baz=bim。
    dataType :服务端返回数据的类型。如果不设置这个选项,jQuery 会根据服务端返回数据的 MIME 类型自行判断。
    error :当 Ajax 执行错误时将会触发的回调函数,该函数接受原始的请求信息及状态码。
    jsonp :执行 JSONP 请求时需要制定的回调函数名称,默认值是“callback”。
    success :Ajax 成功执行时将会触发的回调函数。在函数中可获取服务端返回的信息(如果 dataType 被设置成 JSON,返回的数据应该是一个 JavaScript 对象),当然也可获取服务端返回的原始数据信息及状态码。
    timeout :给 Ajax 请求设置一个超时是时间,单位是毫秒。
    type :指定请求的方式,GET 或者 POST,默认值是 GET。其它如 PUT 和 DELETE 方式也可以用,但并不是所有浏览器都支持。
    url :要请求的 URL。

其中 url 选项是所有选项中唯一的一个必选项,其它选项都是可选的。
一些简便方法

如果你不需要那么多可配置的选项,也不关心 Ajax 执行错误时候的相关处理,jQuery 同样提供了一些非常有用的简便方法,以更简洁的方式完成 Ajax 请求。其实这些简便写法只是封装了 $.ajax,并把某些选项预先设定好。

jQuery 提供的简便方法如下:

  •     $.get :对给定的 URL 执行 GET 请求。
  •     $.post :对给定的 URL 执行 POST 请求。
  •     $.getScript :向页面中添加脚本。
  •     $.getJSON :执行一个 GET 请求,服务端返回的信息应为 JSON。

以上每种简便方法中都可传递如下参数:

    url :所请求的 URL,必须提供。
    data :向服务端发送的数据,可选。可以是一个对象,亦或查询字符串,如 foo=bar&baz=bim。

  •         备注:此选项不适用于 $.getScript。

    一个回调函数 :此回调函数在请求成功执行后被触发。可选。该回调函数接受服务端返回的数据,也包括请求的状态码及原始对象。
    数据类型 :服务端返回数据的类型。可选。

  •         备注:此选项只适用于那些在其名称中没指定数据类型的方法。

下面是三个简便方法的示例:

// 获取纯文本或者 html
$.get('/users.php', { userId : 1234 }, function(resp) {
  console.log(resp);
});

// 向页面中添加脚本,然后执行脚本中定义的函数。
$.getScript('/static/js/myScript.js', function() {
  functionFromMyScript();
});

// 从服务端获取 JSON 格式的数据。
$.getJSON('/details.php', function(resp) {
  $.each(resp, function(k, v) {
    console.log(k + ' : ' + v);
  });
});

$.fn.load

$.fn.load 方法是 jQuery 所有 Ajax 方法中唯一在选择器结果集上调用的方法。$.fn.load 方法从给定的 URL 上获取信息,然后填充到选择器结果集包含的元素中。另外,在 URL 后面还可以附加一些选择器,jQuery 最终只会把跟选择器相匹配的内容填充到对应的 HTML 元素中。

下面是示例:

$('#newContent').load('/foo.html');

// 或
$('#newContent').load('/foo.html #myDiv h1:first', function(html) {
 alert('加载完毕!');
});

Ajax 和 表单

在跟表单打交道方面,jQuery 的 Ajax 更显神威。最为有用的两个方法就是 $.fn.serialize 和 $.fn.serializeArray,下面是它们的用法:

// 将表单中数据转化为查询字符串
$('#myForm').serialize();

$('#myForm').serializeArray();
// 将表单中数据转化为对象数组,如:
[
  { name : 'field1', value : 123 },
  { name : 'field2', value : 'hello world' }
]

使用 JSONP

JSON 的本质其实是一种跨站点脚本注入。现在有很多比较好的网站都提供了 JSONP 服务,允许我们用他们预先定义好的 API 获取他们的数据。下面是一个示例,来源于 http://www.giantflyingsaucer.com/blog/?p=2682

服务端代码:

<?php
  header("content-type: text/javascript");

  if(isset($_GET['name']) && isset($_GET['callback'])) {
    $obj->name = $_GET['name'];
    $obj->message = "Hello " . $obj->name;

    echo $_GET['callback']. '(' . json_encode($obj) . ');';
  }
?>

客户端代码:

$.ajax({
  url: 'http://otherDomail.com:8080/JSONP/jsonp-demo.php',
  data: {name: 'Super man'},
  dataType: 'jsonp',
  jsonp: 'callback',
  success: function( response ) {
    console.log( response.message );
  }
});

jQuery 把 JSONP 的实现细节隐藏在幕后,我们要做的就是告诉 jQuery 服务端定义好的函数名以及我们请求的数据类型是 JSONP,其它方面和普通的 Ajax 请求没什么区别。
Ajax 事件

很多时候我们都需要在 Ajax 请求开始或结束时做一些操作,例如显示或隐藏一个 loading… 图片。这些工作本可以在每个 Ajax 请求中各自实现,但是 jQuery 提供了更好的方法,你可以像绑定普通事件一样绑定 Ajax 事件。若要参阅全部事件列表,可访问 http://docs.jquery.com/Ajax_Events。下面是简单示例:

$('#loading_indicator')
  .ajaxStart(function() { $(this).show(); })
  .ajaxStop(function() { $(this).hide(); });

 

Javascript 相关文章推荐
JQuery中的html()、text()、val()区别示例介绍
Sep 01 Javascript
js读写json文件实例代码
Oct 21 Javascript
JavaScript给按钮绑定点击事件(onclick)的方法
Apr 07 Javascript
javascript实现给定半径求出圆的面积
Jun 26 Javascript
微信小程序 教程之wxapp视图容器 swiper
Oct 19 Javascript
AngularJS指令与指令之间的交互功能示例
Dec 14 Javascript
Angular指令封装jQuery日期时间插件datetimepicker实现双向绑定示例
Jan 22 Javascript
AngularJS 打开新的标签页实现代码
Sep 07 Javascript
JavaScript中的高级函数
Jan 04 Javascript
vue 使用element-ui中的Notification自定义按钮并实现关闭功能及如何处理多个通知
Aug 17 Javascript
javascript实现简单搜索功能
Mar 26 Javascript
vue使用screenfull插件实现全屏功能
Sep 17 Javascript
JavaScript的面向对象编程基础
Aug 13 #Javascript
JavaScript简单判断复选框是否选中及取出值的方法
Aug 13 #Javascript
JavaScript实现将文本框的值插入指定位置的方法
Aug 13 #Javascript
JavaScript的jQuery库中function的存在和参数问题
Aug 13 #Javascript
js实现仿Discuz文本框弹出层效果
Aug 13 #Javascript
深入学习JavaScript中的原型prototype
Aug 13 #Javascript
javascript获取本机操作系统类型的方法
Aug 13 #Javascript
You might like
PHP 开发工具
2006/12/06 PHP
php 404错误页面实现代码
2009/06/22 PHP
php将gd生成的图片缓存到memcache的小例子
2013/06/05 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十二)
2014/06/25 PHP
php结合正则获取字符串中数字
2015/06/19 PHP
PHP实现带进度条的Ajax文件上传功能示例
2019/07/02 PHP
php-fpm超时时间设置request_terminate_timeout资源问题分析
2019/09/27 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
再次更新!MSClass (Class Of Marquee Scroll通用不间断滚动JS封装类 Ver 1.6)
2007/02/05 Javascript
javascript 获取url参数和script标签中获取url参数函数代码
2010/01/22 Javascript
javascript重复绑定事件造成的后果说明
2013/03/02 Javascript
iframe异步加载实现点击左边菜单加载右边内容实例讲解
2013/03/04 Javascript
node.js中的buffer.copy方法使用说明
2014/12/14 Javascript
每天一篇javascript学习小结(Boolean对象)
2015/11/12 Javascript
jquery拖拽效果完整实例(附demo源码下载)
2016/01/14 Javascript
基于d3.js实现实时刷新的折线图
2016/08/03 Javascript
使用clipboard.js实现复制功能的示例代码
2017/10/16 Javascript
vue-router3.0版本中 router.push 不能刷新页面的问题
2018/05/10 Javascript
关于jquery中attr()和prop()方法的区别
2018/05/28 jQuery
vue项目中使用百度地图的方法
2018/06/08 Javascript
ECharts地图绘制和钻取简易接口详解
2019/07/12 Javascript
[00:37]DOTA2上海特级锦标赛 Secert 战队宣传片
2016/03/03 DOTA
你所不知道的Python奇技淫巧13招【实用】
2016/12/14 Python
python 定时器每天就执行一次的实现代码
2019/08/14 Python
基于python全局设置id 自动化测试元素定位过程解析
2019/09/04 Python
Pytorch 数据加载与数据预处理方式
2019/12/31 Python
解决Pycharm双击图标启动不了的问题(JetBrains全家桶通用)
2020/08/07 Python
美国购买和销售礼品卡平台:Raise
2017/01/13 全球购物
平面设计的岗位职责
2013/11/08 职场文书
企业内部培训方案
2014/02/04 职场文书
《伯牙绝弦》教学反思
2014/03/02 职场文书
供用电专业求职信
2014/07/07 职场文书
机关副主任个人四风问题整改措施
2014/09/26 职场文书
2016年大学生暑期社会实践活动总结
2016/04/06 职场文书
推荐六本经典文学奖书籍:此生必读
2019/08/22 职场文书
django学习之ajax post传参的2种格式实例
2021/05/14 Python