You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"Открутить назад" завершившийся генератор нельзя, но можно создать новый ещё одним вызовом `generateSequence()` и выполнить его.
82
82
83
+
[smart header="`function* (…)` или `function *(…)`?"]
84
+
Технически можно ставить звёздочку как сразу после `function`, так и позже, перед названием. В интернет можно найти обе эти формы записи, они верны:
85
+
```js
86
+
function*f() {
87
+
// звёздочка после function
88
+
}
89
+
90
+
function*f() {
91
+
// звёздочка перед названием
92
+
}
93
+
```
94
+
95
+
Автор этого текста полагает, что правильнее использовать первый вариант `function*`, так как звёздочка относится к типу объявляемой сущности (`function*` -- "функция-генератор"), а не к её названию. Конечно, это всего лишь рекомендация-мнение, не обязательное к выполнению, работать будет и так и эдак.
96
+
[/smart]
97
+
98
+
99
+
100
+
83
101
## Генератор -- итератор
84
102
85
103
Как вы, наверно, уже догадались по наличию метода `next()`, генератор является итерируемым объектом.
@@ -595,35 +613,112 @@ co(function*() {
595
613
});
596
614
```
597
615
598
-
**Библиотеку`co`можно использовать один раз в самом внешнем вызове.**
616
+
Библиотека`co`обрабатывает результаты рекурсивно. То есть, если в результате `yield` получается генератор, то он тоже выполняется библиотекой `co`, и так далее.
599
617
600
-
Библиотека `co` обрабатывает результаты рекурсивно. То есть, если в результате `yield`получается генератор, то ...
618
+
Звучит это сложнее, чем на самом деле. Практическое следствие простое -- мы можем использовать `yield`во вложенных вызовах функций.
601
619
602
-
TODO
620
+
Например:
621
+
622
+
```js
623
+
//+ run
624
+
'use strict';
625
+
626
+
function*gen() {
627
+
returnyieldgen2();
628
+
}
629
+
630
+
function*gen2() {
631
+
let result =yieldnewPromise(
632
+
resolve=>setTimeout(resolve, 1000, 'hello')
633
+
);
634
+
return result;
635
+
}
636
+
637
+
co(function*() {
638
+
let result =yieldgen();
639
+
alert(result); // hello
640
+
});
641
+
```
642
+
643
+
В примере выше: первый `yield` возвращет генератор `gen()`, при его выполнении `yield'ится` генератор `gen2()`, внутри которого `yield'ится` промис, который завершается с `"hello"`.
644
+
645
+
Библиотека `co` при этом -- только на самом верхнем уровне.
646
+
647
+
Пример `showUserAvatar()` можно переписать с использованием `co` вот так:
648
+
649
+
```js
650
+
//+ run
651
+
'use strict';
603
652
653
+
// Загрузить данные пользователя с нашего сервера
654
+
function*fetchUser(url) {
655
+
let userFetch =yieldfetch(url);
656
+
657
+
let user =yielduserFetch.json();
658
+
659
+
return user;
660
+
}
661
+
662
+
// Загрузить профиль пользователя с github
663
+
function*fetchGithubUser(user) {
664
+
let githubFetch =yieldfetch(`https://api.github.com/users/${user.name}`);
yield new Promise(resolve => setTimeout(resolve, 3000));
703
+
yieldsleep(2000);
619
704
620
705
img.remove();
621
706
622
707
returnimg.src;
623
708
}
624
709
710
+
co(showUserAvatar);
711
+
```
712
+
713
+
Заметим, что для перехвата ошибок при получении аватара используется `try..catch` вокруг `yield* fetchAvatar`. Несмотря на то, что операции -- асинхронные, мы можем использовать обычный `try..catch`. И это очень удобно!
0 commit comments