eRIZ's weblog

PHP, webdesign, Linux, Windows i inne, bo nie samym chlebem człowiek żyje

AJAX w jQuery i callbacki JavaScript

O tym, że jQuery jest niezłym narzędziem, nie trzeba nikogo przekonywać. Filozofia łańcuchowania – mam na myśli konstrukcję – nie jest jednak taka oczywista w użytku pod każdym względem. Z jQuery da się wygodnie pracować; to, że coś nie wychodzi wcale nie oznacza, iż trzeba od razu zmieniać używanego frameworka.

Wystarczy zrozumieć kilka rzeczy. ;) Notka jest przeznaczona dla raczej początkujących; starzy wyjadacze pewnie niczego nowego się nie dowiedzą.

Sposób przekazywania zdarzeń

Zacznijmy od tego, jak skonstruowana jest większość funkcji, które pozwalają precyzować własne zdarzenia. Jest to niejako spowodowane konstrukcją samego języka. Przypomnijmy sobie dwie funkcje udostępniane przez przeglądarki oraz sposób podstawiania parametrów. Mam tu na myśli setInterval i setTimeout. Jeden z parametrów, to czas; drugi – zmienna przechowująca funkcję.

Tak, tak – jeśli do tej pory o tym nie wiedziałeś(aś) – w jQuery zmienna może być funkcją (również w innych językach możemy spotkać tego typu konstrukcje). Tak samo podpina się zdarzenia dla różnych obiektów, ale teraz wracam do tematu. ;)

Callbacki w praktyce

Callback jest to – innymi słowy – funkcja uruchamiana przez jQuery/przeglądarkę, gdy jest wywoływane określone zdarzenie. I tutaj kluczowa uwaga – funkcja ta jest wywoływana asynchronicznie – czyli niezależnie od tych wykonywanych w dalszym ciągu skryptu.

Wróćmy jeszcze do przykładu z setTimeout:

setTimeout(function(){ alert('testujemy!') }, 5000);
alert('a wczesniej?');

Jak myślisz, co pokaże przeglądarka jako pierwsze? Testujemy, a zaraz po nim a wcześniej? Otóż nie – będzie dokładnie na odwrót, z tą różnicą, iż testujemy zostanie ukazane po 5 sekundach. Wynika to właśnie z powodu asynchroniczności. To tak, jakbyśmy programowali coś w stylu wielowątkowych skryptów.

Co z AJAX?

Wrzućmy teraz na warsztat jakieś proste żądanie AJAX napisane w jQuery:

$.get('skrypt.php', function(data){ alert('data'); });

Na pewno zauważyłeś analogię do powyższego przykładu. Tu również mamy do czynienia z callbackiem. Nie zawsze jest to komfortowa sytuacja, zwłaszcza w przypadku sprawdzania jakichś danych przez osobną funkcję, np:

function checkLogin(login){
     $.get('skrypt', { user: login }, function(data){ return data; });
}
alert(checkLogin('ja'));

I co wówczas? Funkcja nie zwróci niczego. Teraz wyjaśnijmy, dlaczego tak się dzieje. Otóż – konstrukcja return użyta w callbacku zwraca dane – tak naprawdę – do frameworka, a nie do naszej funkcji. Jest to dość częsty błąd, który wymaga nieco potu. Zacznijmy od najprostszego rozwiązania…

Żądanie synchroniczne

Obiekt XmlHttpRequest, z którego korzysta każda biblioteka AJAX posiada własność umożliwiającą wysłanie żądania synchronicznego. Pozwala ono na uzyskanie mniej-więcej takiego efektu:

function checkLogin(login){
     var result = '';
     $.ajax({url: 'skrypt', data: { user: login }, success: function(data){ result = data; }, async: false});
     return result;
}

Niestety, ma to dość poważną wadę – działanie skryptów jest zamrażane na czas żądania, co uniemożliwia działanie innych wątków naszej aplikacji.

Wykorzystanie callbacków

Pozostaje – w takim razie – wykorzystać w jakiś sposób wspomniane przeze mnie wyżej callbacki.

function checkLogin(login, callback){
     $.get('skrypt', { user: login; }, function(data){ callback((data=='ok') });
});
}

Co spowoduje wywoływanie funkcji podanej jako callback z parametrem bool (prawda/fałsz). W naszym skrypcie można zrealizować to mniej więcej w ten sposób:

var login = $('#login').val();
checkLogin(login, function(isFree){
     if(isFree){
          alert('login jest wolny');
     }else{
          alert('login jest zajęty');
     }
});

Wadą tego rozwiązania jest konieczność umieszczenia dalszej logiki funkcji w callbacku, co nie musi być koniecznie czytelne. Zaletą – możliwość zachowania wielowątkowości (np. Sprawdzanie wielu pól naraz).

Jak to wygląda?

No sam(a) widzisz.  Sęk w tym, iż nie ma – mi znanego – jakiegoś innego sposobu, który umożliwiłby strukturalne przetworzenie takiego kodu. Wynika to głównie ze specyfiki oraz kontekstu wywoływania funkcji obsługi zdarzeń.

2 komentarze

dopisz swój :: trackback :: RSS z komentarzami

RSS z komentarzami :: trackback

Skomentuj

Możesz używać znaczników XHTML. Dozwolone są następujące tagi: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">

Wszystkie komentarze przechodzą przez moderację oraz filtry antyspamowe. Nie zostanie opublikowany komentarz, jeśli:

  • Jego treść obraża kogokolwiek.
  • W treści znajdują się wulgaryzmy i słownictwo ogólnie uznane za nieprzyzwoite.
  • Mam wątpliwości co do autora wpisu (Wszelkie anonimy są kasowane - niezależnie od zawartości - wpisz prawdziwy e-mail. Jeśli usunąłem, Twoim zdaniem, komentarz niesłusznie - daj znać). Zdarza się, iż sprawdzam kim jest komentujący.
  • Zawiera jakąkolwiek formę reklamy.

Warning: Undefined variable $user_ID in /usr/home/er1zpl/domains/eriz.pcinside.pl/public_html/weblog/wp-content/themes/inBlueDiary/comments.php on line 112

Szufladka