LAB11 - nvbach91/4IZ268-2022-2023-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>
    <h2>${article.title}</h2>
    <p>${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 (let key in product) {
    console.log(key, product[key]);
}
  • forEach loop (iterace v poli, pokud nebudeme přerušovat)
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 Array.map
const numbers = [1, 2, 3, 4];
const squares = numbers.map((val) => {  
    return val * val;  
});
// 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
const intervalId = setInterval(() => {
  console.log('every 1 second');  
}, 1000); // Calls a function at specified intervals

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

clearInterval(intervalId);

clearTimeout(timeoutId);

JavaScript good practice

  • ukládat věci z DOMu do proměnných, pokud s nimi budeme pracovat opakovaně
  • nevytvářet globální proměnné (pod scope window)
  • nepoužívat == (!=) ale === (!==),
  • inicializovat proměnné
  • nemodifikovat DOM opakovaně (v cyklu)

Knihovny pro JavaScript

  • import knihovny - na pořadí záleží, pokud knihovna je závislá na jiné
  • používat zminifikovanou verzi
  • populární 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>

JSON

  • JavaScript Object Notation
  • Datový formát / Syntaxe pro ukládání a výměnu dat
    • Kolekce klíč-hodnota dvojic - 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 sevrveru a jak je poslat na server? pomocí AJAX
$.getJSON('https://jsonplaceholder.typicode.com/users').done((resp) => {
  console.log(resp);
});
$.ajax({ 
  url: 'https://jsonplaceholder.typicode.com/users',
  method: 'GET',
  dataType: 'json',
}).done((resp) => {
  console.log(resp);
});

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 AJAXem: data se posílají v pozadí pomocí JavaScriptu a podle výsledku se stránka aktualizuje za běhu, žádné přesměrovávání - pak se jedná o tzv. Single Page (AJAX) Aplikace
  • usecase: Uživatel může pokračovat v práci zatímco program načítá data v pozadí
  • pomocí AJAX můžeme
    • aktualizovat 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. můžeme vytvářet asynchronní webové aplikace
  • AJAX je kombinace HTML, CSS, JavaScript, DOM, XHR, JSON, XML, …
  • doporučeným datovým formátem pro přenos je právě JSON
  • browsery mají zabudovaný objekt XMLHttpRequest pro asynchronní komunikace s externími servery. Nebo lze použít knihovny třetích stran
  • příklad volání klasické:
// built-in object for HTTP Requests GET
var xhr = new XMLHttpRequest();
var url = 'https://jsonplaceholder.typicode.com/posts';
xhr.open('GET', url);
xhr.addEventListener('load', function () {  // callback
  var data = JSON.parse(xhr.responseText);
});
xhr.addEventListener('error', function (e) {  // callback
  console.error('XHR error', e);
});
xhr.send();
  • příklad volání v jQuery:
// callback style
$.ajax({
  method: 'GET', // or POST, DELETE, OPTIONS ...
  url: 'https://jsonplaceholder.typicode.com/posts',
  success: (resp) => {...},
  error: (error) => {...},
});

// Promise style - recommended!
$.ajax({...})                    // $.get({...}) OR $.post({...}) 
  .done((resp) => {...})
  .fail((resp) => {...})
  .always((resp) => {...})
  .then((resp) => {...});
  • vyvarujte se callback hell

image

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

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(...);
});

Promise

  • co je to Promise? - objekt reprezentující eventuální ukončení / selhání asynchronní operace včetně její výsledky. - cit. MDN
$.ajax({...}) // vrací Promise - thenable
$.get({...})  // vrací Promise - thenable
$.post({...}) // vrací Promise - thenable
  • dostaneme objekt, na kterém lze volat metodu then(callback), jejíž callback se zavolá při ukončení asynchronní operace, podobně jako v případě eventListeneru
$.ajax({...}).then((response) => { 
  doSomethingWith(response);
});
  • Promise nám umožňuje lépe kontrolovat asynchronní kód, abychom neupadli do tzv. Callback Hellu.
  • Na jQuery Promise objektu obvykle zavoláme metody done, fail a always
$.ajax({...})  
  .done((resp) => { doSomethingWhenDoneWith(resp); })
  .fail((resp) => { doSomethingWithWhenFailWith(resp); })
  .always((resp) => { doSomethingAnyway(); });
  • jQuery AJAX events - lze zachytávat události a spustit
$.ajaxStart(cb)    // pokud odstartuje první Ajax request na stránce
$.ajaxStop(cb)     // pokud se doběhnou všechny Ajax requesty na stránce
$.ajaxComplete(cb) // pokud doběhne jakýkoli Ajax request
$.ajaxSuccess(cb)  // pokud jakýkoliv Ajax request doběhne správně
$.ajaxError(cb)    // pokud jakýkoliv Ajax request skončí s chybou
$.ajaxSend(cb)     // se před odesláním jakékoliv Ajax requestu
  • paralelní volání HTTP požadavků v jQuery
$.when(
  $.getJSON('/abc').done((resp) => { doSomethingWith(resp); }),
  $.getJSON('/def').done((resp) => { doSomethingWith(resp); }),
  $.getJSON('/ghi').done((resp) => { doSomethingWith(resp); }),
  $.getJSON('/jkl').done((resp) => { doSomethingWith(resp); })
).then(() => {
  console.log('All promises have resolved');
});

Wireframe aplikace

image

Návrh SP2

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