JSON with Padding – czyli zdalny Ajax

Istnieje kilka sposobów na pobieranie danych ze zdalnego serwera. Ajax sam w sobie nie pozwala na to, chyba że stosując odpowiednie nagłówki i metodę GET.

W tym wpisie przedstawię kolejną technikę – JSON with Padding. Jest to wzorzec wykorzystania lekkiego formatu wymiany danych zgodnego z JavaScript – JSON.

Zasada działania

Nikt nie zabroni nam załadować pliku ze skryptem JavaScript z serwera w innej domenie. Załóżmy, że działamy na domenie ‚yarpo.pl’. Chcemy załadować framework jQuery z ogólnie dostępnego urla: ‚http://code.jquery.com/jquery-1.6.min.js‚.

<html>
<head>
    <title>Przykład Ajax - zdalny serwer JSONP</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.min.js"></script>
</head>
<body></body></html>

Nikogo nie dziwi takie rozwiązanie.

A przecież można by w ten sposób odwołać się do jakiegoś skryptu. Co więcej przesłać jakieś dane, a w zamian otrzymać odpowiednie dane, np. w JSON-ie.

<html>
<head>
    <title>Przykład Ajax - zdalny serwer JSONP</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script type="text/javascript" src="http://yarpo.pl/download/examples/jsonp.php?a=10&amp;b=dane"></script>
</head>
<body></body></html>

Na stronie pod podanym adresem umieściłem skrypt:

[php]<?php
echo ‚{"a":"’ . $_GET[‚a’] . ‚","b":"’ . $_GET[‚b’] . ‚"}’;[/php]

W wyniku takiego rozwiązania otrzymujemy ciąg JSON w pobranym skrypcie ze zdalnego serwera. W przypadku Ajax dane te otrzymywaliśmy w jakiejś funkcji. Tu otrzymujemy je w sposób, który nie pozwala automatycznie na wykonanie tego kodu.

„Callback” JSONP

Zamiast przekazania jedynie prostych danych, przekażmy taki skrypt (wywołanie funkcji z odpowiednimi danymi):

[javascript]callbackJsonp({dane : true, obsluz : ‚teraz’, wywolanie :  1});[/javascript]

Stosując takie rozwiązanie nie musimy przekazywać do funkcji JSON. Może to być literał obiektowy.

Zmieńmy zatem kod poprzedniego skryptu PHP:

[php]<?php
echo ‚callbackJsonp({a:"’ . $_GET[‚a’] . ‚",b:"’ . $_GET[‚b’] . ‚"});’;[/php]

Po takiej zmianie, na naszej stronie musi istnieć także funkcja `callbackJsonp’.

<html>
<head>
    <title>Przykład Ajax - zdalny serwer JSONP</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script type="text/javascript">
    function callbackJsonp(obj)
    {
        alert(obj.a + "\n" + obj.b);
    }
    </script>
    <script type="text/javascript" src="http://yarpo.pl/download/examples/jsonp_callback.php?a=10&amp;b=dane"></script>
</head>
<body></body></html>

W wyniku wyświetlone zostanie komunikat:

[text]10
alert[/text]

Takie rozwiązanie jednak nie pozwala na odczyt dowolnych danych, w dowolnym momencie. Dane są odczytywane podczas ładowania się strony. Idea JSONP pozwala na asynchroniczne żądania.

Asynchroniczne żądania JSONP

Możemy zmodyfikować poprzedni przykład w taki sposób, aby odpowiedni plik był ładowany dynamicznie w odpowiedzi na jakieś zachowanie internauty.

<html>
<head>
    <title>Przykład Ajax - zdalny serwer JSONP</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script type="text/javascript">
    function callbackJsonp(obj)
    {
        alert(obj.a + "\n" + obj.b);
    }
    function jsonpRequest(url)
    {
        var oScript = document.createElement("script");
        oScript.setAttribute('src', url);
        oScript.setAttribute('type', 'text/javascript');
        document.body.appendChild(oScript);
    }
</script>
</head>
<body>
    <button onclick="jsonpRequest('http://yarpo.pl/download/examples/jsonp_callback.php?a=10&amp;b=dane')">
        Test
    </button>
</body></html>

Takie rozwiązanie zaczyna mieć ręce i nogi. Pozwala na odebranie danych w odpowiednich warunkach, niekoniecznie podczas ładowania strony, ale w dowolnym momencie.

Brakuje jeszcze oczyszczenia drzewa DOM z niepotrzebnych znaczników <script />. Można to zrobić po wczytaniu skryptu – dla przeglądarek `onload’ oraz dla IE `onreadystatechange’.

<html>
<head>
    <title>Przykład Ajax - zdalny serwer JSONP</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script type="text/javascript">
    function callbackJsonp(obj)
    {
        alert(obj.a + "\n" + obj.b);
    }
    function jsonpRequest(url)
    {
        var oScript = document.createElement("script");
        oScript.setAttribute('src', url);
        oScript.setAttribute('type', 'text/javascript');
        document.body.appendChild(oScript);
        oScript.onload = function()
        {
            this.parentNode.removeChild();
        }
        oScript.onreadystatechange = function()
        {
            if ('loaded' === this.readyState || 'completed' === this.readyState)
            {
                this.parentNode.removeChild(this);
            }
        }
    }
</script>
</head>
<body>
    <button onclick="jsonpRequest('http://yarpo.pl/download/examples/jsonp_callback.php?a=10&amp;b=dane')">
        Test
    </button>
</body></html>

Dzięki takiemu rozwiązaniu zyskaliśmy możliwość pobierania danych ze zdalnego serwera. Technika ta powinna działać na każdej przeglądarce obsługującej JavaScript.

Warto przeczytać:

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *