jQuery - Ajax

Przed poniższą lekturą warto byś przypomniał sobie dział o asynchroniczności i ajaxie. Sporo rzeczy tutaj będzie się powtarzać.

$.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 => { //readuję 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(data, xhr, textStatus) { //gdy wszystko ok
        ...
    },
    error(xhr, textStatus, errorThrown) { //gdy błąd połączenia
        ...
    },
    complete(xhr, textStatus) { /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(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((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((response1, response2, response3) => {
        console.log(response1); //odpowiedź z 1 zapytania
        console.log(response2); //odpowiedź z 2 zapytania
        console.log(response3); //odpowiedź z 3 zapytania
    });

Wszelkie prawa zastrzeżone. Jeżeli chcesz używać jakiejś części tego kursu, skontaktuj się z autorem.
Aha - i ta strona korzysta z ciasteczek.

Menu