1. 程式人生 > >jquery.getJSON跨域方案實現原理

jquery.getJSON跨域方案實現原理

jquery.getJSON在實現與後臺程式非同步互動方面非常的方便,在不牽扯跨域的情況下,實現也很簡單。

使用方法為:
$.getJSON('http://***.**/test/test.php', {'uid':1235,'cid':5678}, function(data){
    if(data.success == 1){
        alert(data.message+'\n'+data.success+'\n'+data.uid);
    }else{
        alert('你錯了');
    }
});

後臺處理程式:
<?php
$cid = $_GET['cid'];
$uid = $_GET['uid'];
$response['cid'] = $cid;
$response['uid'] = $uid;
if($uid > 1234){
    $response['success'] = 1;
}else{
    $response['success'] = 0;
}
$response['message'] = '您的請求成功';
echo json_encode($response);

相比較而言,對於跨域的getJSON實現略顯複雜:來看jquery是如何實現的,比如我前端頁面傳送一個請求
$.getJSON(
    'http://***.**/test/test.php?jsoncallback=?',
    {'uid':1235,'cid':5678},
    function(data){
        if(data.success == 1){
            alert(data.message+'\n'+data.success+'\n'+data.uid);
        }else{
            alert('你錯了');
        }
    }
);

發現這種請求比同域的請求,url地址多了一項引數——jsoncallback,此引數名自定義。而後臺程式在處理的時候會把此jsoncallback引數連同資料一起返回給前端。
<?php
$callback = $_GET['jsoncallback'];
$cid = $_GET['cid'];
$uid = $_GET['uid'];
$response['cid'] = $cid;
$response['uid'] = $uid;
if($uid > 1234){
    $response['success'] = 1;
}else{
    $response['success'] = 0;
}
$response['message'] = '您的請求成功';
echo $callback . '(' . json_encode($response) .')';

此jsoncallback作為資料一起返回給了前端,它在跨域方面起什麼作用呢? 通過檢視firebug的響應資料可以發現,他是jquery自動生成的函式名稱。

接下來,我們來一起看jquery.getJSON程式碼原理。 一步步跟進來看,首先找到getJSON方法:
getJSON: function( url, data, callback ) {
        return jQuery.get( url, data, callback, "json" );
},

ok,重點關注引數callback向後溯源get方法:
jQuery.each( [ "get", "post" ], function( i, method ) {
    jQuery[ method ] = function( url, data, callback, type ) {
        // shift arguments if data argument was omitted
        if ( jQuery.isFunction( data ) ) {
            type = type || callback;
            callback = data;
            data = undefined;
        }
        return jQuery.ajax({
            type: method,
            url: url,
            data: data,
            success: callback,
            dataType: type
        });
    };
});


發現是走的ajax方法: 其實getJSON方法等同於dataType為'json'的ajax方法,再向下探究ajax方法:
// Bind script tag hack transport
jQuery.ajaxTransport( "script", function(s) {

    // This transport only deals with cross domain requests
    if ( s.crossDomain ) {
        var script,
            head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
        return {
            send: function( _, callback ) {
                script = document.createElement( "script" );
<span style="white-space:pre">		</span>script.async = "async";
                if ( s.scriptCharset ) {
                    script.charset = s.scriptCharset;
                }
                script.src = s.url;
                // Attach handlers for all browsers
                script.onload = script.onreadystatechange = function( _, isAbort ) {
                    if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
                        // Handle memory leak in IE
                        script.onload = script.onreadystatechange = null;
                        // Remove the script
                        if ( head && script.parentNode ) {
                            head.removeChild( script );
                        }
                        // Dereference the script
                        script = undefined;
                        // Callback if not abort
                        if ( !isAbort ) {
                           callback( 200, "success" );
                        }
                    }
                };
                // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
                // This arises when a base node is used (#2709 and #4378).
                head.insertBefore( script, head.firstChild );
            },

跨域檢查有一個例外那就是HTML的<Script>標記;我們可以<Script>的src屬性,來訪問獨立域名下或者其它站點的js資源。這個url響應的結果可以有很多種,比如JSON,返回的Json值成為<Script>標籤的src屬性值,這就是運用了jsonp的方法載入一個js。