Михаил Давыдов
Разработчик JavaScript
Асинхронность,
работа с
сервером
3
Задача
•  Качаем 1 файл
•  Обрабатываем
•  После отправляем данные на 2 сервера
•  Вызываем alert()
4
Псевдокод программы
var file = getFile('/filename.jpg');
file = jpg2png(file);
sendFile(file, 'http://server1.ru/');
sendFile(file, 'http://server2.ru/');
alert('tada!');
5
1. Подготовка
var file = getFile('/filename.jpg');
file = jpg2png(file);
sendFile(file, 'http://server1.ru/');
sendFile(file, 'http://server2.ru/');
alert('tada!');
Старт TCP/IP сессии
Отправка HTTP запроса
Получение данных
…
6
2. Обработка
var file = getFile('/filename.jpg');
file = jpg2png(file);
sendFile(file, 'http://server1.ru/');
sendFile(file, 'http://server2.ru/');
alert('tada!');
Переделываем JPG в PNG
7
3. Отправка
var file = getFile('/filename.jpg');
file = jpg2png(file);
sendFile(file, 'http://server1.ru/');
sendFile(file, 'http://server2.ru/');
alert('tada!');
Старт TCP/IP сессии
Отправка HTTP запроса
Получение данных
…
8
4. Алерт
var file = getFile('/filename.jpg');
file = jpg2png(file);
sendFile(file, 'http://server1.ru/');
sendFile(file, 'http://server2.ru/');
alert('tada!');
Рисуем окно через системное API
9
Схема загрузки линейной программы
время
БлокировкаБлокировка Блокировка
Загрузка Отправка Отправка
Подготовка Обработка Отправка Алерт
10
Большую часть времени эта
программа ждет I/O
11
Стоимость операций I/O
• L1-кэш 3 цикла
• L2-кэш 14 циклов
• RAM 250 циклов
• Диск 41 000 000 циклов
• Сеть 240 000 000
12
На помощь приходят: треды,
потоки, форки…
13
дедлоки, мьютексы,
проблемы с синхронизацией
и параллельное
программирование
14
Событийная программа
16
Идея событийного программирования
•  Любое действие – событие
–  Начало программы
–  Клик на кнопку
–  Событие во времени
–  Конец чтения файла…
•  Программа не ждет I/O
–  Загрузка процесса предельно близка к 100%
•  Подписывается на события I/O
•  Выполняет код, когда событие наступило
17
Сообщи мне когда придет
файл, а пока я буду делать
что-то полезное
18
Псевдокод событийной программы
var servers = [
'http://serv1.ru/',
'http://serv2.ru/'];
getFile('filename.jpg').then(function (file){
file = jpg2png(file);
sendTo(file, servers).then(function (){
alert('tada!');
});
});
19
1. Подготовка
var servers = [
'http://serv1.ru/',
'http://serv2.ru/'];
getFile('filename.jpg').then(function (file){
file = jpg2png(file);
sendTo(file, servers).then(function (){
alert('tada!');
});
});
Когда файл скачается вызови эту функцию
20
2. Обработка
var servers = [
'http://serv1.ru/',
'http://serv2.ru/'];
getFile('filename.jpg').then(function (file){
file = jpg2png(file);
sendTo(file, servers).then(function (){
alert('tada!');
});
});
Кодируем в PNG
21
3. Отправка
var servers = [
'http://serv1.ru/',
'http://serv2.ru/'];
getFile('filename.jpg').then(function (file){
file = jpg2png(file);
sendTo(file, servers).then(function (){
alert('tada!');
});
});
Когда файлы отправятся вызови эту функцию
22
4. Алерт
var servers = [
'http://serv1.ru/',
'http://serv2.ru/'];
getFile('filename.jpg').then(function (file){
file = jpg2png(file);
sendTo(file, servers).then(function (){
alert('tada!');
});
});
Рисуем системное окно
23
Схема загрузки событийной программы
время
Ожидание Ожидание
Запрос
Подготовка Обработка Отправка Алерт
24
Профит
•  Блокировка → Ожидание запроса
•  Программа не блокируется
•  Отправляет файлы параллельно
•  1 тред может обслуживать несколько
соединений
25
Event Loop
26
Event Loop
•  Один поток
•  Использует системные команды
–  *NIX: select, epoll, kqueue
–  Win: GetMessage, PeekMessage
•  Основа – список событий
•  Подписываемся на событие
•  Выполняем код, когда событие произошло
•  Список событий пуст – конец
27
Кадр или Фрейм Event Loop
=== обработчик события
28
Event Loop
var servers = [
'http://serv1.ru/',
'http://serv2.ru/'];
getFile('filename.jpg').then(function (file){
file = jpg2png(file);
sendTo(file, servers).then(function (){
alert('tada!');
});
});
Список событий
Когда придет запрос к серверу – запусти этот код
Запрос к серверу
29
Event Loop
var servers = [
'http://serv1.ru/',
'http://serv2.ru/'];
getFile('filename.jpg').then(function (file){
file = jpg2png(file);
sendTo(file, servers).then(function (){
alert('tada!');
});
});
Список событий
Пришел запрос к северу, выполняем обработчик
Когда файл прочитается – запусти этот код
Файл прочитан
30
Event Loop
var servers = [
'http://serv1.ru/',
'http://serv2.ru/'];
getFile('filename.jpg').then(function (file){
file = jpg2png(file);
sendTo(file, servers).then(function (){
alert('tada!');
});
});
Список событий
Файл прочитался, выполняем обработчик
Когда файлы отправятся – запусти этот код
Файл отправлен
Файл отправлен
31
А что если будет несколько
одновременных запросов?!
32
Фрейм 0 выполняем код программы
Запрос к серверу
Список событий
Старт программы +	

Сейчас выполняется
33
Фрейм N пришел Запрос 1
Запрос к серверу Запрос к серверу
Список событийСейчас выполняется
Файл прочитан 1+
34
Фрейм N+1 пришел Запрос 2
Запрос к серверу Запрос к серверу
Список событийСейчас выполняется
Файл прочитан 1
Файл прочитан 2+
35
Фрейм N+2 прочитался Файл 1
Запрос к серверу
Список событийСейчас выполняется
Файл прочитан 1
Файл прочитан 2
+	

 Файл отправлен 1
Файл отправлен 1+
36
Фрейм N+3 еще Запрос 3
Запрос к серверу
Список событийСейчас выполняется
Файл прочитан 2
Файл отправлен 1
Файл отправлен 1
Запрос к серверу
Файл прочитан 3+
37
Фрейм N+4 Файлы 1 отправили
Запрос к серверу
Список событийСейчас выполняется
Файл прочитан 2
Файл прочитан 3
Файл отправлен 1
Файл отправлен 1
Затем
38
Фрейм N+5 Файлы 2 прочитали
Запрос к серверу
Список событийСейчас выполняется
Файл прочитан 3
Файл прочитан 2
+	

 Файл отправлен 2
Файл отправлен 2+
39
Фрейм N+6 Файлы 3 прочитали
Запрос к серверу
Список событийСейчас выполняется
Файл прочитан 3
Файл отправлен 2
Файл отправлен 2
+	

 Файл отправлен 3
Файл отправлен 3+
40
Фрейм N+7 Файлы 3 отправили
Запрос к серверу
Список событийСейчас выполняется
Файл отправлен 3
Файл отправлен 3
Затем
Файл отправлен 2
Файл отправлен 2
41
Фрейм N+8 Файлы 2 отправили
Запрос к серверу
Список событийСейчас выполняется
Файл отправлен 2
Файл отправлен 2
Затем
42
Фрейм N+100500 убираем обработчик
Список событий
Убрать событие
Сейчас выполняется
43
Когда очередь пуста –
программа завершается
44
Таймеры в JavaScript
45
Таймеры это не sleep() –
это события во времени,
они используют Event Loop
46
Таймер без повтора
•  setTimeout(function, timeout): Number
–  выполни эту функцию не раньше чем через это время
–  таймаут - миллисекунды
•  clearTimeout(timerId)
–  предотврати выполнение этого таймера
–  ид таймера – обычное число
47
setTimeout(function () {
console.log(1);
}, 1000);
var timerId = setTimeout(function () {
console.log(2);
}, 1000);
console.log(3);
clearTimeout(timerId);
// 3, 1
Пример setTimeout
48
Таймер c повтором
•  setInterval(function, timeout): Number
–  выполняй эту функцию через данный интервал
–  интервал - миллисекунды
•  clearInterval(timerId)
–  предотврати выполнение этого интрвала
–  ид интервала – обычное число
49
var times = 10;
var intervalId = setInterval(function () {
console.log(new Date());
times--;
if (!times) {
clearInterval(intervalId);
}
}, 1000);
Пример setInterval
50
Любой таймер будет вызван
не раньше указанного
времени
51
var time = new Date();
setTimeout(function () {
console.log(new Date() - time);
}, 1000);
// Эта функция выполняется 1100 мсек
thisFunctionTakes1100msec();
// 1102
Пример промаха таймера
52
JavaScript работает
в одном потоке и не может
прерывать обработчики
53
Что происходит
Получить текущее время
Подписаться на событие T+1000
Тяжелая функция (1100 мс)
Время
T+1000
Выполнение функции таймера
Запаздывание
54
Таймеры выполняются в
том же потоке, что и
программа
55
var time = new Date();
setTimeout(function () {
console.log(new Date() - time);
}, 1000);
setTimeout(function () {
// Эта функция выполняется 1100 мсек
thisFunctionTakes1100msec();
}, 10);
thisFunctionTakes1100msec();
// 2212 = 1100 + 10 + 1100 + x
Еще один пример промаха таймера
56
Таймер может никогда не
выполниться
57
var time = new Date();
setTimeout(function () {
console.log(new Date() - time);
}, 1000);
while(true);
Пример не достижимого таймера
58
Время I/O > Время вычислений
Лучше Event Loop
59
Время I/O < Время вычислений
Лучше Thread или Fork
60
Работа с сервером
61
Асинхронная работа с
сервером
62
AJAX – Асинхронный
JavaScript и XML
63
Много разных API и хаков
•  XMLHttpRequest
•  EventSource
•  WebSockets
•  JSONP
64
XMLHttpRequest aka XHR
•  Предполагали использовать XML
•  Победил JSON
•  XML остался
65
Возможности XMLHttpRequest
•  Неблокирующие запросы
–  GET, POST, PUT, DELETE, …
–  Можно отправлять и блокирующие
•  Нельзя отправлять на другой сервер
–  В версии 2 можно
66
// GET запрос
var xhr = new XMLHttpRequest();
// Подготавливаем запрос
xhr.open('GET', 'http://server.ru/file.jpg', true);
// Подписываемся на событие "изменение статуса"
xhr.addEventListener('readystatechange', function () {
// Когда ответ пришел
if (xhr.readyState === 4) {
// Печатаем тело ответа
console.log(xhr.responseText);
}
}, false);
// Отправляем запрос
xhr.send();
Работа с XHR
67
Статусы XMLHttpRequest
•  UNSENT=0
–  функция open() еще не вызвана
•  OPENED=1
–  функция send() еще не вызвана
•  HEADERS_RECEIVED=2
–  Пришли заголовки
•  LOADING=3
–  часть ответа пришла
•  DONE=4
–  запрос завершен
https://developer.mozilla.org/en-US/docs/DOM/
XMLHttpRequest
68
Методы и свойства XHR
•  open(method, url, isNotBlock)
–  method – 'get', 'post', …
–  url – 'http://pewpew.com', '/file.jpg', 'file.jpg', '//site.ru:8080/'
•  send(body)
–  body – post тело 'name=name&time=1345678&message=hello'
•  readyState: Number
•  responseText: String
•  status: Number
–  HTTP статус ответа – 200, 404, 500
•  addEventListener(event, function)
•  ...
https://developer.mozilla.org/en-US/docs/DOM/
XMLHttpRequest
69
Сделаем обертку над XMLHttpRequest
Асинхронный XHR
function asyncXHR(method, url, data, callback) {
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback(null, xhr.responseText);
} else {
callback('error');
}
}
});
xhr.send(data);
}
70
Когда статус изменится – вызови эту функцию
Асинхронный XHR
function asyncXHR(method, url, data, callback) {
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback(null, xhr.responseText);
} else {
callback('error');
}
}
});
xhr.send(data);
}
71
Если статус = "Готово" – проверяем статус ответа
Асинхронный XHR
function asyncXHR(method, url, data, callback) {
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback(null, xhr.responseText);
} else {
callback('error');
}
}
});
xhr.send(data);
}
72
Если статус ответа 200 (все хорошо) – вызываем функцию с данными
Асинхронный XHR
function asyncXHR(method, url, data, callback) {
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback(null, xhr.responseText);
} else {
callback('error');
}
}
});
xhr.send(data);
}
73
Используем
asyncXHR('get', 'http://site.ru', null,
function (err, data) {
if (!err) {
console.log(data);
}
});
Стало на много меньше кода
74
Перепишем наш абстрактный пример
asyncXHR('get', 'filename.jpg', null, processThenSendFile);
function processThenSendFile(err, file) {
file = jpg2png(file);
asyncXHR('post', '//site.ru/', file, alertWhenDone);
}
function alertWhenDone(err, status) {
alert('tada');
}
75
Заключение
•  Линейная программа
–  треды
–  форки
–  потоки
•  Событийная программа
–  Любой I/O – событие
•  Event Loop
•  Таймеры
•  Асинхронная работа с сервером
–  AJAX
–  XMLHttpRequest aka XHR
76
Михаил Давыдов
Разработчик JavaScript
azproduction@yandex-team.ru
azproduction
Спасибо

JavaScript. Event Loop and Timers (in russian)

  • 2.
  • 3.
    3 Задача •  Качаем 1файл •  Обрабатываем •  После отправляем данные на 2 сервера •  Вызываем alert()
  • 4.
    4 Псевдокод программы var file= getFile('/filename.jpg'); file = jpg2png(file); sendFile(file, 'http://server1.ru/'); sendFile(file, 'http://server2.ru/'); alert('tada!');
  • 5.
    5 1. Подготовка var file= getFile('/filename.jpg'); file = jpg2png(file); sendFile(file, 'http://server1.ru/'); sendFile(file, 'http://server2.ru/'); alert('tada!'); Старт TCP/IP сессии Отправка HTTP запроса Получение данных …
  • 6.
    6 2. Обработка var file= getFile('/filename.jpg'); file = jpg2png(file); sendFile(file, 'http://server1.ru/'); sendFile(file, 'http://server2.ru/'); alert('tada!'); Переделываем JPG в PNG
  • 7.
    7 3. Отправка var file= getFile('/filename.jpg'); file = jpg2png(file); sendFile(file, 'http://server1.ru/'); sendFile(file, 'http://server2.ru/'); alert('tada!'); Старт TCP/IP сессии Отправка HTTP запроса Получение данных …
  • 8.
    8 4. Алерт var file= getFile('/filename.jpg'); file = jpg2png(file); sendFile(file, 'http://server1.ru/'); sendFile(file, 'http://server2.ru/'); alert('tada!'); Рисуем окно через системное API
  • 9.
    9 Схема загрузки линейнойпрограммы время БлокировкаБлокировка Блокировка Загрузка Отправка Отправка Подготовка Обработка Отправка Алерт
  • 10.
    10 Большую часть времениэта программа ждет I/O
  • 11.
    11 Стоимость операций I/O • L1-кэш3 цикла • L2-кэш 14 циклов • RAM 250 циклов • Диск 41 000 000 циклов • Сеть 240 000 000
  • 12.
    12 На помощь приходят:треды, потоки, форки…
  • 13.
    13 дедлоки, мьютексы, проблемы ссинхронизацией и параллельное программирование
  • 14.
  • 15.
  • 16.
    16 Идея событийного программирования • Любое действие – событие –  Начало программы –  Клик на кнопку –  Событие во времени –  Конец чтения файла… •  Программа не ждет I/O –  Загрузка процесса предельно близка к 100% •  Подписывается на события I/O •  Выполняет код, когда событие наступило
  • 17.
    17 Сообщи мне когдапридет файл, а пока я буду делать что-то полезное
  • 18.
    18 Псевдокод событийной программы varservers = [ 'http://serv1.ru/', 'http://serv2.ru/']; getFile('filename.jpg').then(function (file){ file = jpg2png(file); sendTo(file, servers).then(function (){ alert('tada!'); }); });
  • 19.
    19 1. Подготовка var servers= [ 'http://serv1.ru/', 'http://serv2.ru/']; getFile('filename.jpg').then(function (file){ file = jpg2png(file); sendTo(file, servers).then(function (){ alert('tada!'); }); }); Когда файл скачается вызови эту функцию
  • 20.
    20 2. Обработка var servers= [ 'http://serv1.ru/', 'http://serv2.ru/']; getFile('filename.jpg').then(function (file){ file = jpg2png(file); sendTo(file, servers).then(function (){ alert('tada!'); }); }); Кодируем в PNG
  • 21.
    21 3. Отправка var servers= [ 'http://serv1.ru/', 'http://serv2.ru/']; getFile('filename.jpg').then(function (file){ file = jpg2png(file); sendTo(file, servers).then(function (){ alert('tada!'); }); }); Когда файлы отправятся вызови эту функцию
  • 22.
    22 4. Алерт var servers= [ 'http://serv1.ru/', 'http://serv2.ru/']; getFile('filename.jpg').then(function (file){ file = jpg2png(file); sendTo(file, servers).then(function (){ alert('tada!'); }); }); Рисуем системное окно
  • 23.
    23 Схема загрузки событийнойпрограммы время Ожидание Ожидание Запрос Подготовка Обработка Отправка Алерт
  • 24.
    24 Профит •  Блокировка →Ожидание запроса •  Программа не блокируется •  Отправляет файлы параллельно •  1 тред может обслуживать несколько соединений
  • 25.
  • 26.
    26 Event Loop •  Одинпоток •  Использует системные команды –  *NIX: select, epoll, kqueue –  Win: GetMessage, PeekMessage •  Основа – список событий •  Подписываемся на событие •  Выполняем код, когда событие произошло •  Список событий пуст – конец
  • 27.
    27 Кадр или ФреймEvent Loop === обработчик события
  • 28.
    28 Event Loop var servers= [ 'http://serv1.ru/', 'http://serv2.ru/']; getFile('filename.jpg').then(function (file){ file = jpg2png(file); sendTo(file, servers).then(function (){ alert('tada!'); }); }); Список событий Когда придет запрос к серверу – запусти этот код Запрос к серверу
  • 29.
    29 Event Loop var servers= [ 'http://serv1.ru/', 'http://serv2.ru/']; getFile('filename.jpg').then(function (file){ file = jpg2png(file); sendTo(file, servers).then(function (){ alert('tada!'); }); }); Список событий Пришел запрос к северу, выполняем обработчик Когда файл прочитается – запусти этот код Файл прочитан
  • 30.
    30 Event Loop var servers= [ 'http://serv1.ru/', 'http://serv2.ru/']; getFile('filename.jpg').then(function (file){ file = jpg2png(file); sendTo(file, servers).then(function (){ alert('tada!'); }); }); Список событий Файл прочитался, выполняем обработчик Когда файлы отправятся – запусти этот код Файл отправлен Файл отправлен
  • 31.
    31 А что еслибудет несколько одновременных запросов?!
  • 32.
    32 Фрейм 0 выполняемкод программы Запрос к серверу Список событий Старт программы + Сейчас выполняется
  • 33.
    33 Фрейм N пришелЗапрос 1 Запрос к серверу Запрос к серверу Список событийСейчас выполняется Файл прочитан 1+
  • 34.
    34 Фрейм N+1 пришелЗапрос 2 Запрос к серверу Запрос к серверу Список событийСейчас выполняется Файл прочитан 1 Файл прочитан 2+
  • 35.
    35 Фрейм N+2 прочиталсяФайл 1 Запрос к серверу Список событийСейчас выполняется Файл прочитан 1 Файл прочитан 2 + Файл отправлен 1 Файл отправлен 1+
  • 36.
    36 Фрейм N+3 ещеЗапрос 3 Запрос к серверу Список событийСейчас выполняется Файл прочитан 2 Файл отправлен 1 Файл отправлен 1 Запрос к серверу Файл прочитан 3+
  • 37.
    37 Фрейм N+4 Файлы1 отправили Запрос к серверу Список событийСейчас выполняется Файл прочитан 2 Файл прочитан 3 Файл отправлен 1 Файл отправлен 1 Затем
  • 38.
    38 Фрейм N+5 Файлы2 прочитали Запрос к серверу Список событийСейчас выполняется Файл прочитан 3 Файл прочитан 2 + Файл отправлен 2 Файл отправлен 2+
  • 39.
    39 Фрейм N+6 Файлы3 прочитали Запрос к серверу Список событийСейчас выполняется Файл прочитан 3 Файл отправлен 2 Файл отправлен 2 + Файл отправлен 3 Файл отправлен 3+
  • 40.
    40 Фрейм N+7 Файлы3 отправили Запрос к серверу Список событийСейчас выполняется Файл отправлен 3 Файл отправлен 3 Затем Файл отправлен 2 Файл отправлен 2
  • 41.
    41 Фрейм N+8 Файлы2 отправили Запрос к серверу Список событийСейчас выполняется Файл отправлен 2 Файл отправлен 2 Затем
  • 42.
    42 Фрейм N+100500 убираемобработчик Список событий Убрать событие Сейчас выполняется
  • 43.
    43 Когда очередь пуста– программа завершается
  • 44.
  • 45.
    45 Таймеры это неsleep() – это события во времени, они используют Event Loop
  • 46.
    46 Таймер без повтора • setTimeout(function, timeout): Number –  выполни эту функцию не раньше чем через это время –  таймаут - миллисекунды •  clearTimeout(timerId) –  предотврати выполнение этого таймера –  ид таймера – обычное число
  • 47.
    47 setTimeout(function () { console.log(1); },1000); var timerId = setTimeout(function () { console.log(2); }, 1000); console.log(3); clearTimeout(timerId); // 3, 1 Пример setTimeout
  • 48.
    48 Таймер c повтором • setInterval(function, timeout): Number –  выполняй эту функцию через данный интервал –  интервал - миллисекунды •  clearInterval(timerId) –  предотврати выполнение этого интрвала –  ид интервала – обычное число
  • 49.
    49 var times =10; var intervalId = setInterval(function () { console.log(new Date()); times--; if (!times) { clearInterval(intervalId); } }, 1000); Пример setInterval
  • 50.
    50 Любой таймер будетвызван не раньше указанного времени
  • 51.
    51 var time =new Date(); setTimeout(function () { console.log(new Date() - time); }, 1000); // Эта функция выполняется 1100 мсек thisFunctionTakes1100msec(); // 1102 Пример промаха таймера
  • 52.
    52 JavaScript работает в одномпотоке и не может прерывать обработчики
  • 53.
    53 Что происходит Получить текущеевремя Подписаться на событие T+1000 Тяжелая функция (1100 мс) Время T+1000 Выполнение функции таймера Запаздывание
  • 54.
    54 Таймеры выполняются в томже потоке, что и программа
  • 55.
    55 var time =new Date(); setTimeout(function () { console.log(new Date() - time); }, 1000); setTimeout(function () { // Эта функция выполняется 1100 мсек thisFunctionTakes1100msec(); }, 10); thisFunctionTakes1100msec(); // 2212 = 1100 + 10 + 1100 + x Еще один пример промаха таймера
  • 56.
    56 Таймер может никогдане выполниться
  • 57.
    57 var time =new Date(); setTimeout(function () { console.log(new Date() - time); }, 1000); while(true); Пример не достижимого таймера
  • 58.
    58 Время I/O >Время вычислений Лучше Event Loop
  • 59.
    59 Время I/O <Время вычислений Лучше Thread или Fork
  • 60.
  • 61.
  • 62.
  • 63.
    63 Много разных APIи хаков •  XMLHttpRequest •  EventSource •  WebSockets •  JSONP
  • 64.
    64 XMLHttpRequest aka XHR • Предполагали использовать XML •  Победил JSON •  XML остался
  • 65.
    65 Возможности XMLHttpRequest •  Неблокирующиезапросы –  GET, POST, PUT, DELETE, … –  Можно отправлять и блокирующие •  Нельзя отправлять на другой сервер –  В версии 2 можно
  • 66.
    66 // GET запрос varxhr = new XMLHttpRequest(); // Подготавливаем запрос xhr.open('GET', 'http://server.ru/file.jpg', true); // Подписываемся на событие "изменение статуса" xhr.addEventListener('readystatechange', function () { // Когда ответ пришел if (xhr.readyState === 4) { // Печатаем тело ответа console.log(xhr.responseText); } }, false); // Отправляем запрос xhr.send(); Работа с XHR
  • 67.
    67 Статусы XMLHttpRequest •  UNSENT=0 – функция open() еще не вызвана •  OPENED=1 –  функция send() еще не вызвана •  HEADERS_RECEIVED=2 –  Пришли заголовки •  LOADING=3 –  часть ответа пришла •  DONE=4 –  запрос завершен https://developer.mozilla.org/en-US/docs/DOM/ XMLHttpRequest
  • 68.
    68 Методы и свойстваXHR •  open(method, url, isNotBlock) –  method – 'get', 'post', … –  url – 'http://pewpew.com', '/file.jpg', 'file.jpg', '//site.ru:8080/' •  send(body) –  body – post тело 'name=name&time=1345678&message=hello' •  readyState: Number •  responseText: String •  status: Number –  HTTP статус ответа – 200, 404, 500 •  addEventListener(event, function) •  ... https://developer.mozilla.org/en-US/docs/DOM/ XMLHttpRequest
  • 69.
    69 Сделаем обертку надXMLHttpRequest Асинхронный XHR function asyncXHR(method, url, data, callback) { var xhr = new XMLHttpRequest(); xhr.open(method, url, true); xhr.addEventListener('readystatechange', function () { if (xhr.readyState === 4) { if (xhr.status === 200) { callback(null, xhr.responseText); } else { callback('error'); } } }); xhr.send(data); }
  • 70.
    70 Когда статус изменится– вызови эту функцию Асинхронный XHR function asyncXHR(method, url, data, callback) { var xhr = new XMLHttpRequest(); xhr.open(method, url, true); xhr.addEventListener('readystatechange', function () { if (xhr.readyState === 4) { if (xhr.status === 200) { callback(null, xhr.responseText); } else { callback('error'); } } }); xhr.send(data); }
  • 71.
    71 Если статус ="Готово" – проверяем статус ответа Асинхронный XHR function asyncXHR(method, url, data, callback) { var xhr = new XMLHttpRequest(); xhr.open(method, url, true); xhr.addEventListener('readystatechange', function () { if (xhr.readyState === 4) { if (xhr.status === 200) { callback(null, xhr.responseText); } else { callback('error'); } } }); xhr.send(data); }
  • 72.
    72 Если статус ответа200 (все хорошо) – вызываем функцию с данными Асинхронный XHR function asyncXHR(method, url, data, callback) { var xhr = new XMLHttpRequest(); xhr.open(method, url, true); xhr.addEventListener('readystatechange', function () { if (xhr.readyState === 4) { if (xhr.status === 200) { callback(null, xhr.responseText); } else { callback('error'); } } }); xhr.send(data); }
  • 73.
    73 Используем asyncXHR('get', 'http://site.ru', null, function(err, data) { if (!err) { console.log(data); } }); Стало на много меньше кода
  • 74.
    74 Перепишем наш абстрактныйпример asyncXHR('get', 'filename.jpg', null, processThenSendFile); function processThenSendFile(err, file) { file = jpg2png(file); asyncXHR('post', '//site.ru/', file, alertWhenDone); } function alertWhenDone(err, status) { alert('tada'); }
  • 75.
    75 Заключение •  Линейная программа – треды –  форки –  потоки •  Событийная программа –  Любой I/O – событие •  Event Loop •  Таймеры •  Асинхронная работа с сервером –  AJAX –  XMLHttpRequest aka XHR
  • 76.