jQuery - Ajax
Obsługa AJAX w czystym JavaScript nie zawsze była najwygodniejszą sprawą. Jasne - da się szybko przyzwyczaić (a nawet bardzo szybko), ale niektóre czynności mogą być dość dziwne - szczególnie gdy chcemy by działały na każdej przeglądarce.
Możliwe, że właśnie dlatego bardzo często do działania z AJAX wybierane są biblioteki dające "nakładkę". Jedną z najczęściej wybieranych bibliotek jest właśnie jQuery, która bardzo upraszcza działanie z asynchonicznymi połączeniami.
$.ajax()
Funkcja $.ajax(), bo o niej mowa to główna, a zarazem najbardziej rozbudowana funkcja z tutaj omawianych. Ma ona postać:
$.ajax({
url : "http://localhost:5000/movies", //gdzie się łączymy
method : "post", //typ połączenia, domyślnie get
dataType : "json", //typ danych jakich oczekujemy w odpowiedzi
contentType : "application/json", //gdy wysyłamy dane czasami chcemy ustawić ich typ
data : { //dane do wysyłki
name : "Marcin",
country : "Polska"
})
});
method | typ połączenia: post, get, delete, put, patch. Domyślnym jest get |
---|---|
dataType | typ danych jaki oczekujemy w odpowiedzi. Omówimy go za moment. Jeżeli nie zostanie ustawiony, jQuery spróbuje określić typ danych na podstawie nagłówka Content-Type lub MIME type odpowiedzi. Najczęściej przez nas używanym będzie "json" |
data | obiekt zawierający przekazywane dane. Jeżeli wykonujemy połączenie typu GET, dane zostaną doklejone do adresu po znaku zapytania (jako query string - np. http://localhost:5000?pet=kot&food=myszka) |
contentType | typ danych jakie wysyłamy na serwer. Czasami musimy poinformować serwer jakiego typu dane mu ślemy. Domyślnie używany jest "application/x-www-form-urlencoded; charset=UTF-8 |
W praktyce parametrów możliwych do ustawienia jest o wiele więcej, przy czym najczęściej wystarczą powyższe. Warto jednak przyjrzeć się stronie http://jqapi.com/#p=jQuery.ajax i zapoznać się z kilkoma z nich.
Proste przykłady użycia tej funkcji mogą wyglądać tak jak poniżej:
//pobieranie danych
$.ajax({
url : "http://localhost:5000/movies",
dataType : "json"
})
//wysyłanie danych
$.ajax({
url : "http://localhost:5000/movies",
method : "post",
dataType : "json",
data : {
name : "Karol",
age : 13
}
})
Funkcje zwrotne
Jak wiemy z rozdziału o Ajax, komunikacja zawsze działa na dwa kroki. Wysyłamy dane, i reagujemy na dane, które przychodzą nam z serwera. Aby móc operować na takich zwróconych danych, w przypadku ajax możemy skorzystać w dwóch sposobów.
Po pierwsze możemy użyć funkcji zwrotnych, które są dostępne dla nas w postaci dodatkowych parametrów:
$.ajax({
url : "...",
success : function(response) {...}, //gdy wszystko ok
error : function() {...}, //gdy błąd połączenia
complete : function() {...} //gdy połączenie zakończyło się (błędnie lub pozytywnie)
});
$.ajax({
url : "https://jsonplaceholder.typicode.com/posts",
success : function(response) {
console.log(response);
},
error : function() {
console.log("Wystąpił błąd z połączeniem");
}
});
Jak sobie powiedzieliśmy w rozdziale o Promise, zastosowanie funkcji zwrotnych sprawdza się w wielu sytuacjach, a używanie ich nie jest niczym złym. Są jednak momenty, gdzie korzystanie z ich dobrodziejstw może być problematyczne - szczególnie wtedy, gdy wczytywanie jednych danych zależą od wczytania innych danych.
Wraz z wersją 1.5 do jQuery wprowadzono obiekt $.Deferred, który jest odpowiednikiem Promise dla jQuery. Obiekt taki pozwala nam - podobnie do Promise - skorzystać z dodatkowych metod, które pozwalają reagować na zakończenie obietnicy:
//teoretyczna funkcja wczytująca
function load() {
const d = new $.Deferred();
setTimeout(function() {
d.resolve("superWczytaneDane");
}, 1000);
return d.promise();
}
promise
.done(function(result) {...})
.fail(function() {...})
.always(function() {...});
Z naszego punktu widzenia najważniejsze jest to, że zarówno $.ajax()
, jak i poniżej omawiane skrócone odpowiedniki zwracają taki obiekt, dzięki czemu dla każdej z takich funkcji możemy używać starszych callbacków, ale też omawianych metod.
Są to kolejno:
done() | wywoływane po pomyślnym wysłaniu danych do skryptu (kiedy serwer nie zwrócił błędu typu 400, 404, 500 itp) |
---|---|
fail() | wywoływane gdy nastąpi błąd w połączeniu - np. 404 - nie ma takiego adresu |
always() | wywoływane po zakończeniu połączenia - bez względu czy zakończyło się błędem czy sukcesem |
Użycie takich funkcji może mieć postać:
$.ajax({
url : "..."
})
.done(function(res) {
console.log(res); //dostaliśmy odpowiedź z serwera, wypisujemy ją
})
.fail(function() {
alert("Wystąpił błąd w połączeniu");
})
.always(function() {
$(".loading").hide();
});
//wczytywanie danych z serwera
$.ajax({
url : "http://localhost:3005/users",
dataType : "json"
})
.done(function(response) {
console.log(response);
});
//wysyłanie danych na serwer i wypisanie zwracanej odpowiedzi
$.ajax({
url : "http://localhost:3005/users",
method : "post",
data : {
name : "Marcin",
pet : "pies"
},
dataType : "json"
})
.done(function(response) {
console.log(response);
})
.fail(function() {
$(".form-message").html( "Wystąpił błąd" );
})
//wysyłanie danych w formacie json i wypisanie zwracanej odpowiedzi
const ob = {
name : "Marcin",
pet : {
name : "Szamson",
color : "brown",
speed : 1000000
}
};
$.ajax({
url : "http://localhost:3005/users",
method : "post",
contentType : "application/json",
data : JSON.stringify(ob),
dataType : "json"
})
.done(function(response) {
console.log(response);
})
.fail(function() {
alert("Wystąpił błąd w połączeniu");
})
Skrócone odpowiedniki
jQuery udostępnia nam też kilka funkcji będących alternatywnym, skróconymi wariantami użycia powyżej funkcji $.ajax()
:
$.get() | połączenia typu get |
$.post() | połączenia typu post |
$.getJSON() | pobieranie danych w formacie JSON |
$.getSCRIPT() | pobieranie skryptów Javascript |
$element.load() | wczytywanie zasobów (np. stron, tekstu itp.) |
$.get()
Funkcja $.get() jest skróconym zapisem wywołania funkcji $.ajax()
w postaci:
$.ajax({
url: url,
method: "get",
success: function(response) { ... },
data: { ... }, //opcjonalne - dane do wysłania
});
i służy do wykonywania połączeń typu get. Przykładowe zastosowania tej funkcji mogą mieć postać:
//pobieranie danych
$.get("example.php", function(response){
console.log("Dane otrzymane: ", response);
});
//pobieranie danych z dodatkowym wysłaniem jakiś danych
$.get("example.php", { page : 1 }, function(response){
console.log("Dane otrzymane: ", response);
});
//pobieranie danych z wykorzystaniem funkcji done
$.get("example.php", { page : 1})
.done(function(response) {
console.log(response);
})
.fail(function() {
alert("Wystąpił błąd w połączeniu");
})
.always(function() {
$(".loading").hide();
});
$.post()
Funkcja $.post jest skróconym zapisem wywołania funkcji $.ajax w postaci:
$.ajax({
method: "POST",
url: url,
data: { ... },
success: function(response) { ... },
dataType: dataType
});
i służy do wykonywania połączeń typu post.
Funkcję tą możemy używać na kilka sposobów:
//używając callback
$.post( "ajax/test.html", function(response) {
$(".result").html(response);
});
//korzystając z nowych metod
$.post("example.php", {
name: "Johny",
surname: "Bravo"
}).done(function(response) {
console.log("Zapisano pozytywnie: ", response);
});
$.getJSON()
Funkcja $.getJSON() to skrócony zapis konstrukcji:
$.ajax({
dataType: "json",
url: url,
data: data,
success: function(result) { ... },
});
i służy do pobierania danych typu json. Przykładowe użycie tej funkcji może mieć postać:
$.getJSON("test.json", function(res) {
res.forEach(el => console.log(el) );
});
Podobnie do poprzednich funkcji możemy tutaj wysyłać dodatkowe dane i używać nowych funkcji zwrotnych:
$.getJSON("test.json", { id : 100})
.done(function(resp) {
console.log(resp);
})
.fail(function() {
alert("Wystąpił błąd w połączeniu");
});
$.getScript()
Funkcja $.getSCRIPT() to skrócony zapis kodu:
$.ajax({
url: url,
dataType: "script",
success: function(response) { ... },
});
i służy do wczytania i wykonania skryptu JavaScript. Jej przykładowe użycie może mieć postać:
$.getScript("test.js"); //wczytanie i wykonanie skryptu
I znowu - podobnie jak przy innych funkcjach możemy tutaj wysyłać dodatkowe dane i używać nowych funkcji zwrotnych:
$.getScript("test.js")
.done(function( data, textStatus ) {
console.log( data ); //zwrócone dane
console.log( textStatus ); //status wczytania - np. success
})
.fail(function() {
alert("Wystąpił błąd w połączeniu");
});
$element.load()
Ostatnią z omawianych funkcji jest $element.load(), która jest mniej więcej odpowiednikiem kodu $.get(url, data, success)
i służy do wczytywania treści z serwera i umieszczenia jej w jakimś elemencie.
Jej przykładowe użycie może mieć postać:
//wczytuję plik article.html i umieszczam go w div #result
$("#result").load( "article.html" );
//wczytuję plik article.html ale tylko zawartość diva #content
$("#result").load( "article.html #content" );
//wczytuje treść artykułu przekazując dodatkowe dane na serwer - np. id wczytywanego artykułu
$("#result").load( "article.php", { id: 100 } );
//wczytuję dane przekazując dodatkowy parametr
//dodatkowo po wczytaniu danych odpalam funkcję, która pokaże div#result
$("#result").load("feeds.php", { limit: 25 }, function() {
//funkcja zwrotna odpalana po wczytaniu
$("#result").slideDown();
});
Wiele połączeń
Bardzo często zdarza się sytuacja, że musimy pobrać dane z wielu miejsc. Przykładowo mamy użytkownika, który ma swoje dane, ale ma też zbiór filmów itp.
Dzięki obiektowi $.Deferred
możemy korzystać z dodatkowej metody $.when(deferreds), która odpalana jest w momencie, gdy wszystkie przekazane do niej obietnice zostaną wykonane.
const apiUrl = "http://localhost:5000";
$.when(
$.ajax(apiUrl + "/userData"),
$.ajax(apiUrl + "/userMovies"),
$.ajax(apiUrl + "/userPets")
).done(function(resp1, resp2) {
//resp1 i resp2 to tablice ze strukturą: [ data, statusText, jqXHR ]
console.log(res1[0], resp2[0]);
});
function load(endPoint) {
return $.ajax({
url : "http://localhost:5000" + endPoint,
dataType : "json"
});
}
$.when(load("posts"), load("users"), load("todos"))
.done(function(response1, response2, response3) {
console.log(response1); //odpowiedź z 1 ajaxa
console.log(response2); //odpowiedź z 2 ajaxa
console.log(response3); //odpowiedź z 3 ajaxa
});