jQuery - Ajax
$.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", //typ wysyłanych danych
data: { //dane do wysyłki
title: "Przykładowy tytuł",
author: "Karol Nowak",
}
})
.done(res => { //reaguję na odpowiedź - o tym poniżej
console.log(res);
});
W praktyce parametrów możliwych do ustawienia jest ciut więcej.
To co ci powyżej pokazałem, to raczej bardziej rozbudowana wersja tej funkcji. W wielu sytuacjach nie będziesz musiał podawać wszystkich parametrów. Chociażby proste pobranie danych wymaga od nas podania tylko adresu url.
$.ajax({
url: "https://jsonplaceholder.typicode.com/posts"
})
.done(res => {
console.log(res);
});
Warto przy okazji podać też właściwość dataType
, która określa typ danych jakich oczekujemy w odpowiedzi. Jeżeli jej nie podamy, jQuery spróbuje ustalić typ zwróconych danych na podstawie zwróconego z serwera nagłówka "Content-Type"
(co w większości sytuacji powinno być prawidłowe...).
//pobieranie danych
$.ajax({
url: "https://jsonplaceholder.typicode.com/posts",
dataType: "json" //html, json, text, xml, jsonp, script
})
.done(res => {
console.log(res);
});
Podczas wysyłania danych na serwer podajemy je jako obiekt przypisany pod właściwość data
:
//wysyłanie danych za pomocą post
$.ajax({
url: "https://jsonplaceholder.typicode.com/posts",
dataType: "json",
method: "post",
data: {
name: "Karol",
country: "Polska"
}
})
.done(res => {
console.log(res);
});
Domyślnie dane takie są dołączane jako query string dołączany do adresu na który się łączymy.
Jeżeli chcemy wysłać je w innym formacie, musimy dodatkowo ustawić właściwość Content-Type za pomocą właściwości contentType
:
$.ajax({
url: "http://localhost:5000/movies",
method: "post",
dataType: "json",
contentType: "application/json",
data: {
name: "Karol",
country: "Polska"
}
})
.done(res => {
console.log(res);
});
Funkcje zwrotne
Jeżeli chcemy zareagować na odpowiedź z serwera, możemy to zrobić na dwa sposoby.
Po pierwsze możemy użyć funkcji zwrotnych, które są dostępne dla nas w postaci dodatkowych parametrów:
$.ajax({
url: "...",
success(event, XMLHttpRequest, ajaxOptions) { //gdy wszystko ok
...
},
error(event, jqXHR, ajaxSettings, thrownError) { //gdy błąd połączenia
...
},
complete(event, XMLHttpRequest, ajaxOptions) { /gdy połączenie zakończyło się (błędnie lub pozytywnie)
...
} /
});
Przykładowo:
$.ajax({
url: "https://jsonplaceholder.typicode.com/posts",
dataType: "json",
success(data) {
console.log(data);
},
error(xhr, textStatus) {
console.log("Wystąpił błąd z połączeniem:", textStatus);
}
});
Wraz z wersją 1.5 do jQuery wprowadzono obiekt $.Deferred, który jest bardziej rozbudowanym odpowiednikiem obietnic dla jQuery:
function load() {
const defer = $.Deferred(); //tworzę obietnicę
setTimeout(() => {
defer.resolve("ok");
}, 2500);
return defer;
}
load()
.done(res => {
console.log("Wczytano: ", res);
})
Dzięki niemu możemy reagować na asynchroniczne operacje za pomocą funkcji:
done() | wywoływane po pomyślnym zakończeniu asynchronicznej operacji (resolve) |
---|---|
fail() | wywoływane gdy operacja asynchroniczna zakończy się negatywnie (reject) |
always() | wywoływane po zakończeniu asynchronicznej operacji - bez względu na to czy zakończyła się błędem czy sukcesem |
progress() | wywoływane w momencie, gdy obiekt deferred poinformuje o postępie za pomocą funkcji notify() |
const defer = $.Deferred();
setTimeout(() => {
defer.resolve("ok");
}, 2000);
defer.done(res => {
console.log(res);
});
const defer = $.Deferred();
setTimeout(() => {
defer.reject("ok");
}, 2000);
defer.fail(res => {
console.log(res);
});
function load() {
const defer = $.Deferred();
let count = 0;
const interval = setInterval(() => {
count++;
if (count >= 100) {
clearInterval(interval);
defer.resolve("super wczytane dane");
}
defer.notify(count);
}, 1000);
return defer;
}
load()
.done(res => {
console.log("Wczytano: ", res);
})
.always(() => {
console.log("Zakończono wczytywanie");
})
.progress(status => {
console.log("Status wczytywania: ", status);
})
Zamiast powyższych funkcji możemy także skorzystać z odpowiedników metod then()
i catch()
. Działają ona bardzo podobnie jak w czystym Javascript. Różnicą w przypadku jquery jest to, że dla metody then()
możemy przekazać dodatkową trzecią funkcję, która jest odpowiednikiem powyższej funkcji progress()
.
function load() {
const defer = $.Deferred();
setTimeout(() => {
defer.resolve("superWczytaneDane");
}, 1000);
return defer;
}
load()
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
Najważniejszą dla nas sprawą jest to, że zarówno powyżej omawiana funkcja $.ajax()
, jak i poniżej omawiane jej skrócone odpowiedniki zwracają nam taki obiekt, dzięki czemu możemy na ich zakończenie reagować za pomocą wcześniej omawianych właściwości success, complete i error, ale też powyżej omawianych funkcji.
Użycie takich funkcji może mieć więc postać:
//mogę tak
$.ajax({
url: "https://jsonplaceholder.typicode.com/users",
success: (res) => {
console.log(res);
},
error: () => {
alert("Wystąpił błąd w połączeniu");
},
complete: () => {
$(".loading").hide();
}
})
//mogę też tak
$.ajax({
url: "https://jsonplaceholder.typicode.com/users"
})
.done(res => {
console.log(res);
})
.fail(() => {
alert("Wystąpił błąd w połączeniu");
})
.always(() => {
$(".loading").hide();
})
Podobnie do obietnic z czystego Javascript drugi sposób o wiele lepiej sprawdzi się w przypadku pisania funkcji służących do wczytywania danych:
function loadData(url) {
return $.ajax({
url: "https://jsonplaceholder.typicode.com/" + url
})
}
loadData("users")
.done(res => {
console.log(res);
});
Skrócone odpowiedniki
JQuery udostępnia nam też kilka funkcji będących alternatywnymi, skróconymi wariantami użycia powyżej funkcji $.ajax()
. Funkcje te to odpowiednio:
$.get()
Funkcja $.get() służy do wykonywania połączeń typu get. Jest to odpowiednik wywołania funkcji
$.ajax()
w postaci:
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
})
Przykłady użycia:
//pobieram dane i reaguję na odpowiedź za pomocą funkcji zwrotnej
$.get(url, res => {
console.log("Dane otrzymane:", res);
});
//pobranie danych z dołączeniem dodatkowych parametrów jako query string
$.get(url, { page: 1, key: "94381" }, res => {
console.log("Dane otrzymane:", res);
});
//pobieranie danych z wykorzystaniem funkcji done
const dataToSend = {
page: 1,
key: "94381"
}
$.get(url, dataToSend)
.done(res => {
console.log(res);
})
.fail(() => {
alert("Wystąpił błąd w połączeniu");
})
$.post()
Funkcja $.post() służy do wykonywania połączeń typu post. Jest ona odpowiednikiem wywołania
$.ajax()
w postaci:
$.ajax({
method: "post",
url: url,
data: data,
success: success,
dataType: dataType
})
Przykłady użycia:
//wysyłam dane
$.post(url, { page: 1, key: "94381" }, res => {
console.log("Dane otrzymane:", res);
});
//wysyłanie danych i reakcja na odpowiedź
const dataToSend = {
page: 1,
key: "94381"
}
$.post(url, dataToSend)
.done(res => {
console.log(res);
})
.fail(() => {
alert("Wystąpił błąd w połączeniu");
})
$.getJSON()
Funkcja $.getJSON() służy do pobierania danych w formacie JSON. Jest ona odpowiednikiem wywołania
$.ajax()
w postaci:
$.ajax({
dataType: "json",
url: url,
data: data,
success: success
})
Przykłady użycia:
$.getJSON(url, res => {
console.log("Dane otrzymane:", res);
});
//wysyłam dane za pomocą post
$.getJSON(url, { page: 1, key: "94381" }, res => {
console.log("Dane otrzymane:", res);
});
//wysyłanie danych i reakcja na odpowiedź
const dataToSend = {
page: 1,
key: "94381"
}
$.getJSON(url, dataToSend)
.done(res => {
console.log(res);
})
.fail(() => {
alert("Wystąpił błąd w połączeniu");
})
$.getScript()
Funkcja $.getScript() służy do pobierania skryptów Javascript. Jest równocześnie odpowiednikiem wywołania
$.ajax()
w postaci:
$.ajax({
url: url,
dataType: "script",
success: success
})
Przykłady użycia:
$.getScript("ajax/test.js", res => {
console.log("Dane otrzymane:", res);
});
//pobieram skrypt z przekazaniem dodatkowych danych
$.post("ajax/test.js", { userId: 102 }, res => {
console.log("Dane otrzymane:", res);
});
//wysyłanie danych i reakcja na odpowiedź
const dataToSend = {
userId: 102
}
$.post("ajax/test.js", dataToSend)
.done(res => {
console.log(res);
})
.fail(() => {
alert("Wystąpił błąd w połączeniu");
})
$element.load()
Funkcja $element.load() służy do wczytywania treści z serwera i umieszczenia jej w danym 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ę z pliku article.html tylko zawartość diva #content
$("#result").load( "article.html #content" );
//wczytuje dane z article.html przekazując dodatkowe parametry jako query string
$("#result").load( "article.html", { id: 100 } );
$("#result").load("feeds.php", { limit: 25 }, res => {
$("#result").html(res);
$("#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(deferred), która odpalana jest w momencie, gdy wszystkie przekazane do niej obietnice zostaną wykonane.
const apiUrl = "http://przykladowy-adres.pl/";
$.when(
$.ajax(apiUrl + "userData"),
$.ajax(apiUrl + "userMovies"),
$.ajax(apiUrl + "userPets")
).done((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://przykladowy-adres.pl/" + endPoint,
dataType: "json"
});
}
$.when(load("posts"), load("users"), load("todos"))
.done((response1, response2, response3) => {
console.log(response1); //odpowiedź z 1 zapytania
console.log(response2); //odpowiedź z 2 zapytania
console.log(response3); //odpowiedź z 3 zapytania
});