首頁  >  文章  >  web前端  >  詳解JavaScript中jQuery和Ajax以及JSONP的聯合使用_jquery

詳解JavaScript中jQuery和Ajax以及JSONP的聯合使用_jquery

WBOY
WBOY原創
2016-05-16 15:45:141014瀏覽

借助於 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 的 3f1c4e4b6b16bbbd69b2ee476dc4f83a 标签却无此限制,它可以载入任何域下的脚本,jQuery 正是利用了这一点才得以拥有跨域执行 Ajax 的能力。

所谓 JSONP,就是其它域的服务端返回给我们的是 JavaScript 代码,这段代码可以被加载到 HTML 中的 3f1c4e4b6b16bbbd69b2ee476dc4f83a 标签中,这段 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

服务端代码:

<&#63;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) . ');';
  }
&#63;>

客户端代码:

$.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(); });

 

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn