Upload
fdconf
View
6.417
Download
0
Embed Size (px)
Citation preview
Schlecht!Script
Schlecht!Script
function f1*red(a, b) {…}
f1*red(a, b)
function f2*blue(c) {…}
f2*blue(c)
3
Функции имеют цвет
Schlecht!Script
/* OK! */
function outer*blue() {
inner*blue()
}
4
Синие могут вызывать только другие синие функции
/* NOT OK! */
function outer*blue() {
inner*red()
}
Schlecht!Script
/* OK! */
function outer*red() {
inner2*red()
}
5
Красные могут вызывать и красные и синие функции
/* OK! */
function outer*red() {
inner2*blue()
}
Писать и вызывать красные функции больно!
6
Schlecht!Script7
Красные функции нужно называть на немецком!
/* Интерпретатор не поймёт */
function authUser*red() {…}
function getName*red() {…}
Schlecht!Script8
Красные функции нужно называть на немецком!
/* RICHTIG! */
function benutzerAutorisierung!*rot() {…}
function nameErhalten!*rot() {…}
Как писать на Schlecht!Script?
9
JavaScript
JavaScript extends
Schlecht!Script
11
Асинхронные функции это боль
12
JavaScript
• По-другому работают if/else, for, return • Нет try/catch • Ломают абстракцию
13
Асинхронные функции это боль
// выполнять последовательно
for (var i = 0; i < 10; i++) {
if (shouldProcess(i)) {
results.push(process(i));
}
}
14
if/for: синхронно
JavaScript
function maybeProcess(i) {
if (i >= 10) { return; }
shouldProcess(function(should) {
if (should) {
process(i, function(result) {
results.push(result);
maybeProcess(i++);
});
}
maybeProcess(i++);
});
}
maybeProcess(0);
15
if/for: асинхронно
JavaScript
JavaScript
• Не работают if/then, for и т.д. • Нет try/catch • Ломают абстракцию
16
Асинхронные функции это боль
Асинхронностьв JavaScript
17
Андрей Саломатин
Productive Mobile MoscowJS RadioJS
18
@filipovskii
Асинхронность
Множество событий
Единичная операция
20
Асинхронность: два сценария
Чего мы хотим?
Контроля
22
Исключений
23
Единого интерфейса
24
25
КонтроляИсключений
Единого интерфейса
EventEmitter Stream
Async Generators (ES7)
27
Работа с множеством событий
Continuation Passing Style Promises
Coroutines Async/Await (ES7)
28
Работа с асинхронными операциями
ES6
Работа с множеством асинхронных
событий
30
31
Работа с множеством асинхронных событий
EventEmitter
Stream
EventEmitter32
Объект — источник событий
EventEmitter33
Примеры
Browser: XMLHttpRequest
Node: http.Server
EventEmitter
emitter.addEventListener(eventName, cb);
emitter.removeEventListener(eventName, cb);
34
API
EventEmitter35
События XMLHttpRequest
progress (n) load (1) abort (1) error (1)
EventEmitter36
Реализации
Браузер + Node:EventEmitter2, Tiny Emitter
Node:Node EventEmitter
37
Работа с множеством асинхронных событий
EventEmitter
Stream
38
Работа с множеством асинхронных событий
EventEmitter
Stream
Поток данных
Stream39
Stream40
Примеры
Node: fs.createReadStream(path)
Node: gulp.src(pattern)
Stream41
Типы потоков
stylus files css files css prefixed files
gulp.src('*.styl') stylus() autoprefixer() gulp.dest('dist')
Stream42
Типы потоков
источник преобразование преобразование потребитель
gulp.src('*.styl') stylus() autoprefixer() gulp.dest('dist')
43
Stream44
Реализации
Изоморфные: RxJS, Kefir, Bacon.js
Node:Node Streams
45
Работа с множеством асинхронных событий
EventEmitter Stream
46
Контроль
Исключения
Единый интерфейс
EventEmitter, Stream
Работа с асинхронными операциями
47
48
Работа с асинхронными операциями
Continuation Passing Style Promises
Coroutines
Continuation Passing Style49
Примеры
Browser:
navigator.geolocation.getCurrentPosition(cb)
Node:
fs.stat(path, cb)
try {
var user = fetchUser(userId);
var following = fetchFollowingUsers(userId);
var tweets = fetchTweets(following);
handleResult(tweets);
} catch (err) {
handleError(err);
}
50
Получить ленту твитов синхронно
Continuation Passing Style
fetchUser(userId, function(err, user) {
if (err) { return handleError(err); }
fetchFollowingUsers(user, function(err, following) {
if (err) { return handleError(err); }
fetchTweets(following, function(err, tweets) {
if (err) { return handleError(err); }
handleResult(tweets);
});
});
});
51
Получить ленту твитов асинхронно
Continuation Passing Style
fetchUser(userId, function(err, user) {
if (err) { return handleError(err); }
fetchFollowingUsers(user, function(err, following) {
if (err) { return handleError(err); }
fetchTweets(following, function(err, tweets) {
if (err) { return handleError(err); }
handleResult(tweets);
});
52
Получить ленту твитов асинхронно
Continuation Passing Style
holenBenutzer!*rot(userId, function(err, user) {
if (err) { return handleError*blue(err); }
holenFolgendenBenutzer!*rot(user, function(err, following) {
if (err) { return handleError*blue(err); }
holenTweets!*rot(following, function(err, tweets) {
if (err) { return handleError(err); }
53
Получить ленту твитов asynchron!
Continuation Passing Style
54Schlecht!Script
55
Работа с асинхронными операциями
Continuation Passing Style
Promises
Coroutines
56
Работа с асинхронными операциями
Continuation Passing Style
Promises
Coroutines
Объект — асинхронная операция
Promises57
Promises
Promise.prototype.then(successCb, errorCb);
58
API
Promises
fetchUser(userId)
.then(fetchFollowingUsers)
.then(fetchTweets)
.then(handleResult, handleError);
59
API
Promises vs
Continuation Passing Style
60
Promises61
Реализации
jQuery.Deffered Bluebird RSVP Q
62
Работа с асинхронными операциями
Continuation Passing Style
Promises
Coroutines
63
Работа с асинхронными операциями
Continuation Passing Style
Promises
Coroutines
Coroutines64
Coroutines
function getUserName(userId) {
var user = getUser(userId);
return user.name;
}
65
Остановите землю!
Функция, которую можно приостановить и возобновить
позже
Coroutines66
Coroutines
function * getUserName (userId) {
var user = yield getUser(userId);
return user.name;
};
67
Генераторы: шаг 1 из 3
Coroutines
function * getUserName (userId) {
var user = yield getUser(userId);
return user.name;
};
68
Генераторы: шаг 1 из 3
Coroutines
getUserName = co.wrap(function * (userId) {
var user = yield getUser(userId);
return user.name;
});
69
Генераторы: шаг 2 из 3
Coroutines
getUserName = co.wrap(function * (userId) {
var user = yield getUser(userId);
return user.name;
});
70
Генераторы: шаг 2 из 3
Coroutines
userNamePromise = getUserName(userId);
71
Генераторы: шаг 3 из 3
Использовать генераторы для асинхронного кода —
это хак
72
Использовать генераторы для асинхронного кода —
это хак
73
(но я вас не выдам)
Coroutines74
Реализации
Браузер + Node (используют транспайлер):co (generators), task.js (generators)
Node (использует транспайлер):Fibers
75
Работа с асинхронными операциями
Continuation Passing Style
Promises
Coroutines
76
Контроль
Исключения
Единый интерфейс
CPS, Promises, Coroutines
Работа с множеством событий: EventEmitter Stream
Работа с асинхронными операциями: CPS Promise Coroutine
77
ES6
ES7
Работа с асинхронными операциями: Async/Await
Работа с множеством событий: Async Generators
80
ES7
Работа с асинхронными операциями: Async/Await
Работа с множеством событий: Async Generators
81
ES7
Async/Await
getUserName = co.wrap(function * (userId) {
var user = yield getUser(userId);
return user.name;
});
82
Генераторы
Async/Await
async function getUserName(userId) {
var user = await getUser(userId);
return user.name;
}
83
Async/Await
Async/Await
async function getUserName(userId) {
var user = await getUser(userId);
return user.name;
}
84
Асинхронная функция
Асинхронные функции легализованы в ES7
Async/Await85
Работа с асинхронными операциями: Async/Await
Работа с множеством событий: Async Generators
86
ES7
Работа с асинхронными операциями: Async/Await
Работа с множеством событий: Async Generators
87
ES7
Подписка на события для людей
Async Generators88
Async Generators
async function doDraw() {
for (ev on observe(win, 'mousemove')) {
draw(ev.clientX, ev.clientY);
}
}
89
События DOM
Async Generators
async function doDraw() {
for (ev on observe(win, 'mousemove')) {
draw(ev.clientX, ev.clientY);
}
}
90
События DOM
Работа с асинхронными операциями: Async/Await
Работа с множеством событий: Async Generators
91
ES7
ES6 и ES7: асинхронные операции
92
fetchUser(userId, function(err, user) {
if (err) { return handleError(err); }
fetchFollowingUsers(user, function(err, following) {
if (err) { return handleError(err); }
fetchTweets(following, function(err, tweets) {
if (err) { return handleError(err); }
handleResult(tweets);
});
});
});
93
Получить ленту твитов: CPS
ES6 и ES7
fetchUser(userId)
.then(fetchFollowingUsers)
.then(fetchTweets)
.then(handleResult, handleError);
94
Получить ленту твитов: Promise
ES6 и ES7
try {
var user = await fetchUser(userId);
var following = await fetchFollowingUsers(userId);
var tweets = await fetchTweets(following);
handleResult(tweets);
catch (err) {
handleError(err);
}
95
Получить ленту твитов: Async/Await
ES6 и ES7
ES6 и ES7: обработка множества событий
96
var handler = function(ev) {
if (canDraw(ev)) {
draw(ev.clientX, ev.clientY);
}
};
window.addEventListener('mousemove', handler);
window.removeEventListener('mousemove', handler); // позже
97
DOM события: EventEmitter
ES6 и ES7
Kefir.fromEvent(window, 'mousemove')
.filter(canDraw)
.onValue(function(ev) {
draw(ev.clientX, ev.clientY)
})
.end(); // позже
98
DOM события: Stream
ES6 и ES7
for (ev on observe(window, 'mousemove')) {
if (canDraw(ev)) {
draw(ev.clientX, ev.clientY);
}
}
99
DOM события: Async Generators
ES6 и ES7
Как перестать отлаживать асинхронный
код и начать жить
100
Определите задачу
101
Обдумайте ограничения
102
Используйте лучшие практики
103
Schlecht!Script?
Спасибо!
bit.ly/async-js
Андрей Саломатин @filipovskii
Frontend DevConf, Минск 18.04.2015