Wyobraź sobie prostą aplikację, która regularanie (ajaxem) ściąga nowe dane z serwera. Bardzo prosty przykład:
szablon html (intex.html):
<html>
<head>
<style>
#message{
background: #dd2222;
opacity: 0;
}
#data{
border: 1px solid grey;
width: 300px;
min-height: 200px;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
</head>
<body>
<div id="message"></div>
<ul id="data"></div>
<script>
// tutaj Javascript*!
</script>
</body>
</html>
*kod javascript, tak mógłby wyglądać gdybyśmy go pisali w jQuery<1.5:
(function() {
var _msg = $(“#message”),
_data = $(“#data”),
_callee = arguments.callee;
$.getJSON(“data.php”, function(data, texrStatus, jqXHR){
_msg.html(data.message).css({opacity: 1}).
animate({opacity: 0}, 5000, “swing”);
$.each(data.data, function(key, val){
$( “
A oto skrypt data.php, która zwraca JSON:
{"message":"new stuff!","data":["<?php echo time()?>","<?php echo date("Y-m-d H:i:s")?>"]}
W miarę rozwoju całego systemu takie funkcje callback obsługujące zapytania rozrastają się i puchną. Od wersji 1.5 jQuery przynosi ze sobą tzw. defferred objects. Wszystkie metody "ajaxowe" zwracają teraz obiekt, który jest "obietnicą" wykonania XHR'a. Oznacza to, że możemy pracować na tym obiekcie i nieco rozluźnić powiązanie poszczególnych "zadań" do wykonania po udanym zapytaniu.
Możemy nasz skrypt obsługujący XHTTPRequest, przepisać w następujący sposób:
(function() {
var _msg = $("#message"),
_data = $("#data"),
_callee = arguments.callee,
_jsonCall = $.getJSON("data.php", function(){
window.setTimeout(function(){_callee();}, 10000)
});
_jsonCall.done(function(data){
_msg.html(data.message).css({opacity: 1}).
animate({opacity: 0}, 5000, "swing");
});
_jsonCall.done(function(data){
$.each(data.data, function(key, val){
$("<li>", {
html: val
}).appendTo(_data);
});
});
})()
Jak widać stary sposób nadal działa (linia 5) - domyślnie zapytanie ma za zadanie się wykonać i wywołać się ponownie za 10 sekund. To co dalej dzieje się z danymi może się zmieniać, więc wyciągnąłem te fragmenty na zewnątrz. W linii 9 pod zdarzenie success podpinam wyświetlenie alertu i wywołanie wszystkich związanych z nim bajerów.
W linii 13 z kolei do tego samego zdarzenia podpinam fragment odpowiadający za wyświetlenie szczegółów na stronie.
Mogę to wszystko zrobić dlatego, że przekazanie funkcji do metody success działa dwojako, w zależności od stanu obiektu Deffered
- Jeśli zapytanie zakończyło się już sukcesem - funkcja jest po prostu odpalana
- W przeciwnym wypadku - jest zakolejkowana do zdarzenia 'success' tego obiektu
Oczywiście to nie koniec możliwości Deferred - nie wspomniałem nawet o tym, że można jako parametr przekazać tablicę funkcji.
Jeśli spodobał Ci się ten artykuł i chciałbyś, żebym napisał więcej przykładów z użyciem deferred objects, to napisz mi proszę o tym w komentarzu.
Pingback: Przykład użycia deffered objects - nowego ficzeru jQuery 1.5 - develway.pl
Jasno i zwięźle, więcej mile widziane :)
dzięki, taki feedback też jak najbardziej mile widziany :)
Znalazłem dziś tego bloga – miło wiedzieć że ktoś w taki przystępny sposób pisze o zakamarkach JS. Czekam na więcej ciekawostek, w tym dotyczących nowości JQuery (co rusz pojawiają się w kolejnych wersjach użyteczne metody, o których miło by było poczytać po polsku). Blog ląduje w RSS :)
Po co te całe deffered objects, skoro od wersji 1.0 można używać po prostu:
$.ajax({url: ‘…’, success: mojaFunkcjaGdySukces, error: mojaFunkcjaGdyBlad});
http://en.wikipedia.org/wiki/Decoupling#Software_Development
Chodzi nie tyle o możliwości techniczne, tak jak mówisz callbacki były dostępne już wcześniej, ale o architekturę aplikacji…