Nauczymy się kilku prostych technik na wykonywanie „requesta” do zewnętrznego API i zaciąganie danych w postaci JSON, aby je następnie wyświetlić na stronie. Piszę o tym, bo w tutorialach z Reacta i WordPressa już to robiliśmy, ale w vanilla JS jeszcze tego nie opisywałem. To taki wstęp do bardziej zaawansowanych technik.

Co będziemy robić – ChuckNorris API

Oto nasz startowy template w HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <p id="joke"></p>
    <button id="jokeBtn">Get Joke!</button>
    <script>
        window.addEventListener("DOMContentLoaded", function(){
            console.log("DOM Fully loaded");
            let jokePara = document.querySelector("#joke");
            let jokeBtn = document.querySelector("#jokeBtn");
        });
    </script>
</body>
</html>

Mamy tutaj pusty <p> oraz <button>, mamy też skrypt, który po załadowaniu drzewa DOM tworzy „handle” do tych elementów. Łączyć się będziemy z API ChuckNorris, możemy nawet dodać sobie ich URL:

const API_URL = "https://api.chucknorris.io/jokes/random";

Pod tym adresem znajdziemy zawsze losowy dowcip o Chucku w formacie JSON. Jeżeli mamy zainstalowane rozszerzenie do Chrome formatujące JSON to powinniśmy zobaczyć coś mniej więcej takiego pod tym adresem:

{
  "categories": [],
  "created_at": "2020-01-05 13:42:22.701402",
  "icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
  "id": "U3Lq8vuxTQ-a58BOm3IZVg",
  "updated_at": "2020-01-05 13:42:22.701402",
  "url": "https://api.chucknorris.io/jokes/U3Lq8vuxTQ-a58BOm3IZVg",
  "value": "Babies cry when they are born because they know they are in a world with Chuck Norris."
}

Jeżeli takiego rozszerzenia nie mamy to zobaczymy to samo, ale bez spacji, kompletnie nieczytelne, więc warto się w takie rozszerzenie zaopatrzyć.

Stara metoda – obiekt XMLHttpRequest

Z kronikarskiego obowiązku o tej metodzie wspominam, bo wykonywanie XHR w 2024 roku to nie jest coś, co chcemy robić. Zaraz zobaczymy dlaczego, a potem porównamy to sobie z bardziej zwięzłymi, nowoczesnymi metodami.

Zaczynamy od dodania event-listenera do naszego przycisku:

jokeBtn.addEventListener('click', function(){
    console.log("Button clicked");
});

Teraz tworzymy obiekt klasy XMLHttpRequest:

console.log("Button clicked");
let xhr = new XMLHttpRequest();

Teraz tworzymy funkcję, która przy zmianie stanu coś wykona:

xhr.onreadystatechange = function() {
 //COŚ         
}

Przy XHR sprawy zaczynają kompilować się bardzo szybko. Teraz musimy pamiętać, że stan nr 4 i status code 200 (to drugie powinniśmy pamiętać niezależnie od technologii, przy jakiej pracujemy) oznacza sukces zaś XHR posiada atrybut resposneText:

xhr.onreadystatechange = function() {
   if (this.readyState == 4 && this.status == 200) {
            console.log(xhr.responseText);
       }
} 

To jeszcze nie wszystko – musimy nasz xhr poinformować jaka metoda HTTP ma zostać użyta, pod jaki adres i wysłać ten request:

jokeBtn.addEventListener('click', function(){
       console.log("Button clicked");
       let xhr = new XMLHttpRequest();
       xhr.onreadystatechange = function() {
           if (this.readyState == 4 && this.status == 200) {
                console.log(xhr.responseText);
           }
       }   
        xhr.open("GET", API_URL, true);
        xhr.send();
});

Teraz wyloguje nam nasz dowcip w konsoli. Prawie dobrze. Teraz musimy nasz responseText zamienić na obiekt przy pomocy JSON.parse() i wyświetlić w elemencie <p> to, co twórcy ChuckNorris API trzymają pod kluczem 'value’, czyli treść dowcipu:

if (this.readyState == 4 && this.status == 200) {
       let response = JSON.parse(xhr.responseText);
       joke.textContent = response['value'];
}

Korzystanie z XHR to jest bolesna mordęga. Teraz dla porównania pokażę fragment kodu Reactowo-Wordpressowego, który robi dokładnie to samo i jeszcze ustawia nam stan na value:

const apirequiest = async () => {
	const res = await apiFetch({ url: 'https://api.chucknorris.io/jokes/random' });
	setJoke(res.value);
};

Nie musimy tego rozumieć, ale wystarczy sobie porównać nasz kod, jakieś 18 linijek, do tego. Ale ok – dalej będzie już łatwiej.

Fetch API – lepsza metoda

Wyczyściliśmy sobie nasz listener:

jokeBtn.addEventListener('click', function(){
    console.log("Button clicked");         
});

Dodajemy fetch na nasz URL:

console.log("Button clicked");
fetch(API_URL)

Dodajemy instrukcję „po otrzymaniu odpowiedzi, wyciągnij obiekt JSON:

fetch(API_URL)
.then(response => response.json())

Dodajemy instrukcję „wyloguj to w konsoli”:

fetch(API_URL)
.then(response => response.json())
.then(data => console.log(data))

Teraz sprawiamy, że po wylogowaniu zwrócimy do kolejnego .then już sam dowcip, który w odpowiednim miejscu podmienimy:

fetch(API_URL)
.then(response => response.json())
.then(data => {
      console.log(data);
      return data.value;
})
.then((joke) => {
   jokePara.textContent = joke;
});

Działa, choć robimy to bardziej w celach pokazowych, jak ten cały „pipe” funkcjonuje. Możemy to uprościć, jeżeli nie chcemy nic logować:

fetch(API_URL)
.then(response => response.json())
.then(data => data.value)
.then(joke => jokePara.textContent = joke);

Nawet bardziej uprościć idzie:

fetch(API_URL)
.then(response => response.json())
.then(data => jokePara.textContent = data.value);

XHR a jQuery – też łatwo

Załadujemy sobie bibliotekę jQuery z CDNa i wykonamy jej funkcję ready – odpowiednik (mniej więcej) DOMContentLoaded:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
  $( document ).ready(function() {
      console.log( "ready!" );
    });
</script>

Teraz odpowiednik addEventListener dla eventu 'click’:

$( document ).ready(function() {
    $( "#jokeBtn" ).on( "click", function() {
       console.log("clicked");
      });
});

Teraz połączymy się z API:

$( document ).ready(function() {
    $( "#jokeBtn" ).on( "click", function() {
         $.get( "https://api.chucknorris.io/jokes/random", function( data ) {
              alert( data['value'] );
         });
     });
});

Mamy nasz dowcip wypisany w alercie. Teraz tylko odpowiedni selektor dla naszego <p>, funkcja .text (odpowiednik textContent) i mamy całość:

$( document ).ready(function() {
    $( "#jokeBtn" ).on( "click", function() {
         $.get( "https://api.chucknorris.io/jokes/random", function( data ) {
             $("#joke").text( data['value'] );
         });
     });
});

Jak widać jQuery jest bardzo proste. Kiedyś ta biblioteka była niesamowicie popularna, dzisiaj już czysty JS stał się dużo lepszy, zaś projekty skomplikowane, już nikt nie tworzy stron np. w czystym PHP i JavaScript (który też mocno wyewoluował), żeby aż tak im się chciało tworzyć strony korzystające z jQuery, ale chyba widzimy, że ta popularność nie wzięła się z niczego.

Co dalej?

Cóż, mamy kilka opcji:

  • Biblioteka axios pozwala na wykonywanie API requestów z poziomu bardziej zaawansownych frameworków
  • apiFetch to dobre narzędzie dla korzystających z WordPressa i Reacta, piszących własne bloki
  • Do wykonywania requestów z poziomu WordPressa backendowego mamy wp_remote_get

Umiejąc to, czego nauczyliśmy się dzisiaj, poradzimy sobie z każdą z nich.