Vimeo nie odtwarza tego filmu na tej stronie. Film jest przypisany do poprzedniej domeny.
Krok po Kroku
41 min · JavaScript · Full-stack i Programowanie
Adam GospodarczykZ jednej strony JavaScript jest językiem jednowątkowym (eng. single threaded). Oznacza to że w jednej chwili może być wykonywana wyłącznie jedna operacja. W sytuacji gdy wykonanie jakiejś funkcji zajmuje więcej czasu, pozostałe muszą oczekiwać na jej zakończenie. Pomimo tego możemy wykorzystywać asynchroniczność w JavaScript ponieważ silnik języka udostępnia nam tzw. Web API z pomocą którego część zadań może być wykonywana "w tle" dzięki mechanizmowi o nazwie Event Loop. Daje nam to większe możliwości ale jednocześnie stawia wyzwanie w postaci obsługi kodu asynchronicznego.
Praca z kodem asynchronicznym z natury jest dość mało intuicyjna, w szczególności dla początkujących programistów. Obecnie mamy przynajmniej kilka mechanizmów z których możemy korzystać. Pierwszą z nich są callbacki, czyli funkcje które uruchamiane są w chwili, gdy zadanie asynchroniczne zostanie zakończone. To jednak rodzi problem dotyczący obsługi wielu zdarzeń asynchronicznych oraz może powodować tzw. Inversion of Control, co z kolei może być przyczyną wielu błędów. Poza callbackami do naszej dyspozycji są Promise (obietnice) oraz składnia Async / Await, będąca tzw "syntatic sugar" dla obietnic. Wszystkie z tych technik zostaną omówione podczas warsztatu.
Programowanie funkcyjne jest paradygmatem, którego elementy spotykamy w JavaScript praktycznie na każdym kroku. Z tego powodu bardzo istotne jest to, aby rozumieć pojęcia takie jak funkcje wyższego rzędu (eng. Higher-Order Functions), Currying czy cechy funkcji czystych (eng. Pure Functions). Zrozumienie tych zagadnień oraz umiejętne wykorzystanie ich w praktyce bardzo pomaga w kontekście pracy z JavaScriptem oraz jego asynchroniczną naturą. Przykładowo zrozumienie funkcji wyższego rzędu daje nam większą swobodę w przypadku pracy z callbackami (ale i nie tylko).
Asynchroniczność w JavaScripcie rodzi jeszcze jeden problem - obsługę błędów. W tym celu wykorzystujemy różnego rodzaju techniki, w zależności od sytuacji oraz obranej strategii. Możemy wykorzystywać specjalne callbacki bądź metody .catch do tego aby reagować na ewentualne błędy i wyjątki lub składnię try ... catch ... z której praca również wymaga pewnego doświadczenia. Podczas warsztatu omówimy sobie różne techniki obsługi błędów, oparte o dostępne metody oraz praktyki polecane przez ekspertów.
Niemożliwe jest pisanie kodu JavaScript bez wykorzystania asynchroniczności. Zatem jeżeli sama asynchroniczność to temat z którym nie czujesz się komfortowo, zobacz ten warsztat. Dzięki niemu poznasz zestaw najważniejszych zagadnień i wskazówek, które pozwolą Ci tworzyć lepszy kod. Sama asynchroniczność często pojawia się na rozmowach rekrutacyjnych, zatem znajomość teorii i praktyki może sprawdzić się też w takiej sytuacji.
Warsztat został przygotowany z myślą o osobach, które znają już język JavaScript na poziomie podstawowym lub wyższym i nadal asynchroniczność lub wymienione w podsumowaniu tematy stanowią dla nich wyzwanie. Jednocześnie sam warsztat daje szeroką perspektywę w kontekście rozumienia asynchronicznej natury JavaScriptu oraz zawiera pojęcia m.in. z zakresu programowania funkcyjnego, na których mogą skorzystać bardziej doświadczeni programiści. W warsztacie zostały omówione najważniejsze zagadnienia przydatne w praktyce z pominięciem szczególnie zaawansowanych tematów dotyczących asynchroniczności.
https://wesbos.github.io/Async-Await-Talk/#51
Callback Async - Funkcje · 27 min
const getPokemon = (name, success, error) => {
request(`https://pokeapi.co/api/v2/pokemon/${name}`, (err, res, body) => {
if (err) {
error(err);
}
success(JSON.parse(body));
});
};
const getType = (type, success, error) => {
request(type, (err, res, body) => {
if (err) {
error(err);
}
success(JSON.parse(body));
});
};
getPokemon('ditto', (pokemon) => {
const typeUrl = pokemon.types[0].type.url;
getType(typeUrl, (type) => {
console.log(type);
});
});Higher-Order Function · 4 min
const modify = (x, action) => action(x);
modify(5, (x) => x * 2) /*?*/Currying · 5 min
const curr = (x) => (y) => x + y;
curr(5)(4)Pure functions · 6 min
const nums = [1, 2, 3]
const impure = (arr) => {
arr.forEach((item, index) => (arr[index] = item * new Date())) // Side effects
return arr
}
impure(nums)
console.log(nums)Event Loop · 11 min
function task1() {
console.log('task 1')
return task2()
}
function task2() {
console.log('task 2')
return task3()
}
function task3() {
console.log('task 3')
return task4()
}
function task4() {
return 'done'
}
task1()Callback · 16 min
const multiply = (x, y) => x * y
multiply(5, 4)
const ref = multiply
ref(2, 4)
const double = (x, callback) => callback(x, 2) // Higher Order Function
// Callback #1
double(5, multiply)
// Callback #2
const arr = [1, 2, 3]
arr.filter((i) => i % 2)
// Callback #3
const btn = document.querySelector('btn');
btn.addEventListener('click', () => {
console.log('Click3d!');
});Currying · 21 min
const add = function (a, b) {
return a + b
}
add(3, 5)
const currying = function getA(a) {
return function getB(b) {
return a + b
}
}
const part1 = currying(5)
const part2 = part1(3)
const curry = currying(5)(3)Callback Async · 24 min
const name = 'ditto'
request(`https://pokeapi.co/api/v2/pokemon/${name}`, (err, res, body) => {
if (err) console.log(err)
const pokemonData = JSON.parse(body)
const typeUrl = pokemonData.types[0].type.url
request(typeUrl, (err, res, body) => {
if (err) console.log(err)
const type = JSON.parse(body)
pokemonData.type = type
request(url, () => {
// ...
})
})
})Promise Async · 32 min
const getPokemon = (name) => {
return new Promise((resolve, reject) => {
request(`https://pokeapi.co/api/v2/pokemon/${name}`, (err, response, body) => {
if (err) {
console.log(err)
}
resolve(JSON.parse(body))
})
})
}
const getType = (type, success, error) => {
return new Promise((resolve, reject) => {
request(type, (err, response, body) => {
if (err) {
reject(err)
}
resolve(JSON.parse(body))
})
})
}
getPokemon('ditto')
.then((pokemon) => {
const typeUrl = pokemon.types[0].type.url
getType(typeUrl)
.then((type) => {
console.log(type)
})
.catch((err) => console.log(err))
})
.catch((err) => console.log(err))Async Await · 34 min
const name = 'dittoe';
const data = await fetch(`https://poekeapi.co/api/v2/pokemon/${name}`);
const pokemon = await data.json();
console.log(pokemon);Try catch · 36 min
try {
const name = 'ditto';
const data = await fetch(`https://poekeapi.co/api/v2/pokemon/${name}`);
const pokemon = await data.json();
pokemon.name
} catch (err) {
console.log(err.message);
}Async Await helper · 39 min
const name = 'ditto'
const handleError = (fn) => (...params) =>
fn(...params).catch((err) => {
console.log(err.message)
})
const getPokemon = handleError(async (name) => {
const data = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`)
return await data.json()
})
const pokemon = await getPokemon(name)
console.log(pokemon?.name)