LAB09 - nvbach91/4IZ268-2024-2025-ZS GitHub Wiki

Vývoj webových aplikací - JavaScript

Postřehy z domácích úkolů

  • používat === místo ==, resp. !== místo !=
  • undefined, null, 0, false, NaN, '' jsou "nepravdivé" - lze dávat do if
  • ostatní jsou "pravdivé" - lze dávat do if
  • typeof null === 'object', typeof [] === 'object', typeof new Date() === 'object'
  • ukončit příkazy středníkem!
  • nepoužívat eval()
  • naformátovat kód

Obsah

  • Užitečné funkce a featury v JavaScriptu + ES6
  • Knihovny pro JavaScript
  • jQuery
  • JSON
  • AJAX
  • Wireframe aplikace
  • návrhy SP2

Užitečné features v JavaScriptu + ES6

// classic functions have their own 'this' context
function () { };

// arrow functions don't have their own 'this' context
() => { };
// implicit return
const multiply = (a, b) => a * b;
  • deklarace proměnných pomocí const, let
const inputs = document.querySelectorAll('input');
for (let i = 0; i < inputs.length; i++) { }
  • string interpolation
const name = 'Dave';
const sentence1 = 'My name is ' + name + '.';
const sentence2 = `My name is ${name}.`;
sentence1 === sentence2;

const article = { title: 'Pokemons gone wild', text: 'Lorem ipsum' };
const dom = `
  <article class="post">
    <h2 class="post-heading">${article.title}</h2>
    <p class="post-paragraph">${article.text}</p>
  </article>
`;
  • IIFE (Immediately Invoked Function Expression)
(() => {
    console.log('The IIFE was called');
})();
  • for-in loop (iterace v objektu)
const product = { name: 'Samsung Galaxy Smartphone', price: 10000, currency: 'CZK' };
for (const key in product) {
    console.log(key, ':', product[key]);
}
// name : Samsung Galaxy Smartphone
// price : 10000
// currency : CZK
  • forEach loop (iterace v poli, pokud chceme dojít na konec bez přerušení)
const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8];
let total = 0;
numbers.forEach((number) => {
    total += number;
});
  • transformace položek v poli pomocí metody .map()
const numbers = [1, 2, 3, 4];
const squares = numbers.map((val) => {  
    return val * val;  
});
console.log(squares);
// [1, 4, 9, 16]

const names = ['Dave', 'John', 'Phil', 'Henry'];
const nameItems = names.map((name) => {  
    return `<div class="name">${name}</div>`;  
}).join('');
// nameItems:
//   <div class="name">Dave</div>
//   <div class="name">John</div>
//   <div class="name">Phil</div>
//   <div class="name">Henry</div>
  • další užitečnosti
// Calls a function at specified intervals
const intervalId = setInterval(() => {
  console.log('every 1 second');  
}, 1000);

// Plan and calls a function after a specified amount of time
const timeoutId = setTimeout(() => {
  console.log('after 1 second');
}, 1000);

// Stop the interval
clearInterval(intervalId);

// Cancel the planned function 
clearTimeout(timeoutId);

JavaScript good practice

  • ukládat věci z DOMu do proměnných, jelikož nimi budeme pracovat opakovaně, je zbytečné je znovu vybírat
  • nevytvářet globální proměnné pod scope window
  • nepoužívat == (!=) ale === (!==),
  • proměnné inicializovat přímo v místě deklarace
  • nemodifikovat DOM opakovaně (v cyklu)

Knihovny pro JavaScript

  • import knihovny - na pořadí záleží, pokud knihovna je závislá na jiné
  • importovat minifikovanou verzi
  • knihovny nestahovat k sobě ale používat CDN hosting
<!DOCTYPE html>
<html>
<head></head>
<body>
  <h1>jQuery demo</h1>
  <p>Lorem ipsum</p>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.countdown/2.2.0/jquery.countdown.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pikaday/1.8.0/pikaday.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
  <script src="./js/main.js"></script>
<body>
</html>

jQuery

JSON

  • JavaScript Object Notation
  • Datový formát / Syntaxe pro ukládání a výměnu dat
    • Kolekce klíč-hodnota dvojic - jako JS objekt
    • Uspořádaný seznam hodnot - pole
  • příklad objektu:
{ "klíč1": "hodnota1", "klíč2": "hodnota2" }
  • příklad pole:
[ "hodnota", "hodnota", "hodnota" ]
  • Datové typy: Number, String, Boolean, Object, Array, null
  • JSON Validátor https://jsonlint.com/
  • JavaScriptové methody pro JSON:
JSON.parse();     // create JSON from string
JSON.stringify(); // create string from JSON
  • try/catch pro JSON.parse()
const jsonString = '{"name":"Jack","address":"Washington DC"}';
try {
  const personObject = JSON.parse(jsonString);
} catch (e) {
  console.error(e);
}
  • příklady JSON ze serveru:
// a company object with its information
{
   "name": "Veritas Inc.",
   "capital": 1542000,
   "employees": ["Bill", "Steve", "Elon"],
   "address": {
       "street": "Wall Street 42",
       "city": "New York",
       "state": "NY",
       "country": "United States of America"
   }
}
// array of books and their authors
[
   {
       "title": "Fantastic Beasts",
       "author": "J. K. Rowling",      
       "year": 2001
   },
   {
       "title": "Game of Thrones",
       "author": "George R.R. Martin",      
       "year": 1996
   }
]
  • jak je dostat ze serveru a jak je poslat na server? pomocí AJAX
  • zkusíme fetch() a knihovnu axios
(async () => {
  // using fetch
  try {
    const resp = await fetch('https://jsonplaceholder.typicode.com/users');
    const data = await resp.json();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
  // using axios
  try {
    const resp = await axios.get('https://jsonplaceholder.typicode.com/users');
    console.log(resp.data);
  } catch (err) {
    console.error(err);
  }
})();

(async () => {
  // using fetch
  try {
    const resp = await fetch('https://jsonplaceholder.typicode.com/posts');
    const data = await resp.json();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
  // using axios
  try {
    const resp = await axios.get('https://jsonplaceholder.typicode.com/posts');
    console.log(resp.data);
  } catch (err) {
    console.error(err);
  }
})();

AJAX

  • konvenční webová stránka komunikuje se serverem synchronním způsobem, tj. uživatel vyplní formulář, pošle ho a je přesměrován na jinou stránku s novými informacemi ze serveru
  • s AJAX se data posílají v pozadí pomocí JavaScript Request/Response (XHR) a podle výsledku se stránka aktualizuje (změní se DOM), žádné přesměrovávání - pak se jedná o tzv. Single Page (AJAX) Aplikace
  • Uživatel může pokračovat v práci zatímco program načítá data v pozadí
  • pomocí AJAX můžeme
    • aktualizovat/změnit obsah stránky - bez reloadu stránky
    • načítat data ze serveru - bez reloadu stránky
    • posílat data na server - bez reloadu stránky
  • to vše běží na pozadí - tj. vytváříme tím asynchronní webové aplikace
  • AJAX je kombinace technik pro načítání dat a jejich zobrazení, pomocí HTML, CSS, JavaScript, DOM, XHR, JSON, XML, ...
  • doporučený datový formáte pro přenos je právě JSON
  • browsery mají zabudovaný objekt XMLHttpRequest (XHR) pro asynchronní komunikace s API servery - volání HTTP požadavků, nebo lze použít knihovny třetích stran (axios, jQuery, fetch)
  • příklad volání klasické:
// built-in object for HTTP Requests GET
const xhr = new XMLHttpRequest();
const url = 'https://jsonplaceholder.typicode.com/posts';
xhr.open('GET', url);
xhr.addEventListener('load', () => {  // callback
  const data = JSON.parse(xhr.responseText);
});
xhr.addEventListener('error', (e) => {  // callback
  console.error('XHR error', e);
});
xhr.send();
  • příklad volání v axios
// async/await syntax
(async () => {
  try {
    const resp = await axios.get('https://jsonplaceholder.typicode.com/users');
    console.log(resp.data);
  } catch (err) {
    console.error(err);
  }
  // CRUD operace
  // axios.post, axios.get, axios.put, axios.delete
})();

// promise syntax
axios.get('https://jsonplaceholder.typicode.com/users').then((resp) => {
  console.log(resp.data);
}).catch((err) => {
  console.error(err):
});
  • vyvarujte se callback hell

image

// callback hell example - avoid it using promises or async/await
load('/abc', (abcResp) => {
    load('/def', (defResp) => {
        load('/ghi', (ghiResp) => {
            load('/jkl', (jklResp) => {
                load('/mno', (mnoResp) => {
                    load('/pqr', (pqrResp) => {
                        console.log(...);
                    });
                });
            });
        });
    });
});

// kazdy resp je dostupny pouze v ramci sveho scopu
load('/abc').then((abcResp) => {

    return load('/def');
}).then((defResp) => {

    return load('/ghi');
}).then((ghiResp) => {

    return load('/jkl');
}).then((jklResp) => {

    return load('/mno');
}).then((mnoResp) => {

    return load('/pqr');
}).then((pqrResp) => {

    console.log(...);
});

// vsechny resp jsou dostupne ve scopu
(async () => {
  const abcResp = await load('/abc');
  const defResp = await load('/def');
  const ghiResp = await load('/ghi');
  const jklResp = await load('/jkl');
  const mnoResp = await load('/mno');
  const pqrResp = await load('/pqr');
  console.log(...);
})();

Promise, async/await

  • Promise je objekt reprezentující eventuální ukončení / selhání asynchronní operace včetně její výsledky
axios.post(...)    // vrací Promise - thenable - lze volat .then() nebo s async/await
axios.get(...)     // vrací Promise - thenable - lze volat .then() nebo s async/await
axios.put(...)     // vrací Promise - thenable - lze volat .then() nebo s async/await
axios.delete(...)  // vrací Promise - thenable - lze volat .then() nebo s async/await
  • dostaneme objekt, na kterém lze volat metodu .then(callback) (nebo dát do async/await), jejíž callback se zavolá při ukončení asynchronní operace, podobně jako v případě event listeneru
// pomoci async/await syntax
(async () => {
  const resp = await axios.get(...);
  doSomethingWith(resp.data);
})();
// pomoci promise syntax
axios.get(...).then((resp) => { 
  doSomethingWith(resp.data);
});
  • Promise nebo async/await nám umožňuje lépe kontrolovat asynchronní kód
  • paralelní volání HTTP požadavků v axios
(async () => {
  const responses = await Promise.all([
    axios.get(...),
    axios.get(...),
    axios.get(...),
  ]);
  responses.forEach((resp) => {
    console.log(resp.data):
  });
})():

Wireframe aplikace

image

Návrh SP2

⚠️ **GitHub.com Fallback** ⚠️