Blog webdeveloperski Patryk yarpo Jar

JSON with Padding – czyli zdalny Ajax

Autor wiadomości Maj 7, 2011

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
echo '{"a":"' . $_GET['a'] . '","b":"' . $_GET['b'] . '"}';

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):

callbackJsonp({dane : true, obsluz : 'teraz', wywolanie :  1});

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
echo 'callbackJsonp({a:"' . $_GET['a'] . '",b:"' . $_GET['b'] . '"});';

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:

10
alert

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ć:

Tagged as: , , , Dodaj komentarz
Komentarze (0) Trackbacks (0)

Brak komentarzy.


Leave a comment

 

Brak trackbacków.