This commit is contained in:
Ilya Kantor 2015-07-09 19:17:55 +03:00
parent aa17c0dae8
commit a96409db4b
22 changed files with 155 additions and 109 deletions

View file

@ -0,0 +1,31 @@
# AJAX-запросы: fetch
Метод [fetch](https://fetch.spec.whatwg.org/) -- это `XMLHttpRequest` нового поколения. Он предоставляет улучшенный интерфейс для осуществления запросов к серверу: как по части возможностей и контроля над происходящим, так и по синтаксису, так как построен на промисах.
Поддержка в браузерах пока не очень распространена, но есть [полифилл](https://github.com/github/fetch) и не один.
## Использование
Синтаксис:
Начнём сразу с примера:
```js
//+ run
'use strict';
fetch('/article/fetch/user.json')
.then( response => {
alert(response.headers.get('Content-Type')); // text/html; charset=utf-8
return response.json();
})
.then( user => alert(user.name) ) // iliakan
.catch( alert );
```
Поток такой:
<ul>
<li>

View file

@ -0,0 +1,4 @@
{
"name": "iliakan",
"isAdmin": true
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

View file

@ -1,5 +1,5 @@
# Генераторы
# Генераторы [todo]
Генераторы -- новый вид функций в современном JavaScript. Они отличаются от обычных тем, что могут приостанавливать своё выполнение, возвращать промежуточный результат и далее возобновлять его позже, в произвольный момент времени.
@ -332,4 +332,119 @@ alert( generator.next(9).done ); // true
Исключением является первый вызов `next`, который не может передать значение в генератор, т.к. ещё не было ни одного `yield`.
## generator.throw
Как мы видели в примерах выше, внешний код может вернуть генератору в качестве результата `yield` любое значение.
Можно "вернуть" не только результат, но и ошибку!
Это делает вызов `generator.throw(err)`.
Например:
```js
//+ run
'use strict';
function* gen() {
// Передать вопрос во внешний код и подождать ответа
try {
let result = yield "Сколько будет 2 + 2?";
alert(result);
} catch(e) {
alert(e);
}
}
let generator = gen();
let question = generator.next().value;
*!*
generator.throw(new Error("ответ не найден в моей базе данных"));
*/!*
```
"Вброшенная" извне ошибка обрабатывается как обычно. Она возникает в строке с `yield` и может быть перехвачена `try..catch`, как продемонстрировано выше.
# Плоский асинхронный код
Одна из основных областей применения генераторов -- написание "плоского" асинхронного кода.
Общий принцип такой:
<ul>
<li>Генератор `yield'ит` не просто значения, а промисы.</li>
<li>Есть специальная "функция-чернорабочий" `execute(generator)` которая запускает генератор, последовательными вызовами `next` получает из него эти промисы, ждёт их выполнения и возвращает в генератор результат, пока генератор не завершится.</li>
<li>Последнее значение генератора `execute` возвращает через промис, коллбэк или просто использует, как в примере ниже.</li>
</ul>
Получается примерно так:
```js
//+ run
'use strict';
function* showUserAvatar() {
let userFetch = yield fetch('/article/generator/user.json');
let userInfo = yield userFetch.json();
let githubFetch = yield fetch(`https://api.github.com/users/${userInfo.name}`);
let githubUserInfo = yield githubFetch.json();
let img = new Image();
img.src = githubUserInfo.avatar_url;
img.className = "promise-avatar-example";
document.body.appendChild(img);
yield new Promise(resolve => setTimeout(resolve, 3000));
img.remove();
return img.src;
}
function execute(generator, yieldValue) {
let next = generator.next(yieldValue);
if (!next.done) {
next.value.then(
result => execute(generator, result),
err => generator.throw(err)
);
} else {
// return из генератора (его результат)
alert(next.value);
}
}
*!*
execute( showUserAvatar() );
*/!*
```
[head]
<style>
.promise-avatar-example {
border-radius: 50%;
position: fixed;
right: 0;
top: 0;
}
</style>
[/head]

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 9 KiB

After

Width:  |  Height:  |  Size: 9 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Before After
Before After

View file

@ -0,0 +1,4 @@
{
"name": "iliakan",
"isAdmin": true
}