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.