提示
: Эта статья находится на github«Понимание ECMAScript 6»Заметки организованы, и примеры кода также получены из этого. Вы можете прочитать эту книгу непосредственно, когда у вас есть время. Несмотря на то, что он на английском языке, он прост для понимания и настоятельно рекомендуется.
前情:
в предыдущей статьеВы знаете, почему генераторЗдесь я бросаю много денег и знакомлюgenerator
Причины. В то время партнер указал, что «Генератор используется для имитации спящего механизма многопоточности» и «Генератор работает лениво». В то время я сказал, что в продвинутой главе будет введение, поэтому я расскажу об этом здесь.
摘要:
Дело здесь прежде всего в том, какgenerator
коммуникации, во-первых, использоватьnext()
Передача параметров, во-вторых, вы также можете использоватьthrow()
, отличие в том, что он закинут вовнутрь, второе в том, что естьyield
Когда оператор присваивания,generator
co
Ой).
generator
Не слишком приготовлено, вы можете посмотретьздесь
1. Передача параметров
Проще говоря, вы можетеnext
передать параметры иgenerator
внутриyield
Этот параметр можно получить на следующем примере:
function *createIterator() {
let first = yield 1;
let second = yield first + 2; // 4 + 2
yield second + 3; // 5 + 3
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next(4)); // "{ value: 6, done: false }"
console.log(iterator.next(5)); // "{ value: 8, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
Процесс реализации
Чтобы наглядно объяснить описанный выше процесс выполнения, вы можете использовать эту схему:
Те, у кого одинаковый цвет, выполняются в одной итерации, от светлого к темному, с указанием порядка итераций. Такие как:
- первый звонок
next()
, воплощать в жизньyield 1
остановиться, вернуться{ value: 1, done: false }
.УведомлениеЗатем заявление о назначенииlet fisrt = ...
Не реализована; - второй звонок
next(4)
, сначала установите параметр4
yield
можно понимать как:
let first = yield 1;
=>
let first = 4;
Затем начните выполнение с того места, где была последняя пауза, то есть сначала выполните оператор присваивания.
let first = 4
затем переходите к следующемуyield
пока, т.е.
yield first + 2 // 4 + 2
последнее возвращение{ value: 6, done: false }
Послеnext
Выполнять по указанному выше принципу до завершения итерации.
То есть поnext
параметр,generator
произведеноiterator
, построенный с внешней средоймост связи, в сочетании сiterator
Функция, которая может делать паузу, может делать некоторые интересные вещи, такие как запись обратных вызовов синхронным способом, подробности см. Ниже.
2. кiterator
жеребьевка
function *createIterator() {
let first = yield 1;
let second = yield first + 2; // yield 4 + 2, 然后抛出错误
yield second + 3; // 不会被执行
}
let iterator = createIterator();
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next(4)); // {value: 6, done: false}
console.log(iterator.throw(new Error("Boom"))); // generator 里抛出的错误
В соответствии с механизмом выполнения, упомянутым выше, поток выполнения этого примера может быть представлен этой диаграммой:
В третий раз, когда выполняется итерация, мы вызываемiterator.throw(new Error("Boom"))
, Кiterator
Возникает ошибка, и переданный параметр является сообщением об ошибке.
мы можем преобразоватьcreateIterator
следующим образом:
function* createIterator() {
let first = yield 1;
let second;
try {
second = yield first + 2;
} catch (ex) {
second = 6;
}
yield second + 3;
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next(4)); // "{ value: 6, done: false }"
console.log(iterator.throw(new Error("Boom"))); // "{ value: 9, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
Его поток выполнения объясняется следующим образом:
-
первые два звонка
next
Ситуация такая же, как анализ в механизме исполнения выше, поэтому я не буду вспоминаться. -
третий звонок
iterator.throw(new Error("Boom")
прошлоеgenerator
Выдает ошибку внутри функции, где она в последний раз остановилась, т.е.yield first + 2
Получить информацию, выдать ошибку. но былcatch
, поэтому продолжите выполнение до следующей паузы:yield second + 3; // 6 + 3
Наконец, верните результат этой итерации
{ value: 9, done: false }
-
Продолжайте выполнять другие итерации, ничем не отличающиеся от вышеописанных, поэтому я не буду их повторять.
резюме:Здесь вы можете видеть,
next()
а такжеthrow()
Может сделатьiterator
Продолжайте выполнять, разница в том, что последнее будет выполнено с выдачей ошибкиiterator
продолжать выполнять. Но после этого,generator
Что здесь происходит, зависит от того, как написан код.
3. Generator
внутреннийreturn
утверждение
здесьreturn
Операторы, функционально идентичные обычным функциямreturn
Это не имеет большого значения, он остановитсяreturn
После того, как утверждение выполнено.
function* createIterator() {
yield 1;
return;
yield 2;
yield 3;
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
надreturn
После этогоyield
Они игнорируются, поэтому вторая итерация и умерла.
но еслиreturn
После того, как имеет значение, результат будет учитываться в текущей итерации:
function* createIterator() {
yield 1;
return 42;
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 42, done: true }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
этоiterator
return
значение после{ value: 42, done: true }
.
Кроме того, это возвращаемое значение можно использовать только один раз, поэтому третье выполнениеnext
, возвращаемый результат становится{ value: undefined, done: true }
.
обращать внимание:спред оператор...
а такжеfor-of
увидеть повторяющиеся результатыdone
даtrue
Я немедленно прекращу реализацию.return
Последнее значение также игнорируется и останавливается очень решительно. Как и в примере выше, используйтеfor-of
а также...
воплощать в жизнь:
function* createIterator() {
yield 1;
return 42;
}
let iterator = createIterator();
for(let item of iterator) {
console.log(item);
}
// 1
let anotherIterator = createIterator();
console.log([...anotherIterator])
// [1]
// 猜猜 [...iterator] 的结果是什么
4. Генератор делегата
generator
Что такое делегирование, проще говоряgenerator
делегатыgenerator
B, пусть B сделает это за вас:
function* createNumberIterator() {
yield 1;
yield 2;
}
function* createColorIterator() {
yield "red";
yield "green";
}
function* createCombinedIterator() {
yield* createNumberIterator();
yield* createColorIterator();
yield true;
}
var iterator = createCombinedIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: "red", done: false }"
console.log(iterator.next()); // "{ value: "green", done: false }"
console.log(iterator.next()); // "{ value: true, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
Как видно из вышеизложенного, синтаксис делегирования таков, что вgenerator
в, сyield*
управлять другимgenerator
результат исполнения.
Делегируя различныеgenerator
собрать и использовать повторноreturn
Возвращаемое значение, вы можетеgenerator
function* createNumberIterator() {
yield 1;
yield 2;
return 3;
}
function* createRepeatingIterator(count) {
for (let i = 0; i < count; i++) {
yield "repeat";
}
}
function* createCombinedIterator() {
let result = yield* createNumberIterator();
yield* createRepeatingIterator(result);
}
var iterator = createCombinedIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
Как указано выше,createNumberIterator
Возвращаемое значение3
Он был представленcreateRepeatingIterator
, если разобрать и написать, то вот так:
function* createNumberIterator() {
yield 1;
yield 2;
return 3;
}
function* createRepeatingIterator(count) {
for (let i = 0; i < count; i++) {
yield "repeat";
}
}
function* createCombinedIterator() {
let result = yield* createNumberIterator();
yield result;
yield* createRepeatingIterator(result);
}
var iterator = createCombinedIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
Примечание: поскольку
yield *
с последующимgenerator
результат выполнения иgenerator
даiterable
. то есть,yield *
может непосредственно следоватьiterable
, как строка. Такие как:
let g = function *() {
yield *['a', 'b', 'c']
}
for(let item of g()) {
console.log(item);
}
// a
// b
// c
5. Genarator
Асинхронный
оjs
Характеристики асинхронности в этом расширены здесь. Проще говоря, это позволяетjs
Эти однопоточные языки более мощные, однако, когда асинхронная ситуация сложна, например зависимости между асинхронностью, легко написать следующееcallback hell
, крайне сложно поддерживать:
Разумное использованиеgenarator
genarator
вернутьiterator
, Вам нужно вручную вызватьnext
Куча проблем.那如果封装一些,可以让iterator
Это нормально, это хорошо:
-
Предварительная подготовка, автоматическое выполнение
generator
Функцияrun(function* () { let value = yield 1; console.log(value); value = yield value + 3; console.log(value); });
Чтобы заставить его выполнить себя, затем
run
нужно:- воплощать в жизнь
generator
, получатьiterator
; - передача
iterator.next()
; - Используйте возвращаемый результат предыдущего шага в следующий раз
iterator.next(lastResult)
параметры, продолжайте итерацию; - Повторяйте 3, пока итерация не будет завершена.
Реализация выглядит следующим образом:
function run(taskDef) { // 创建并保存 iterator,留到后面使用 let task = taskDef(); let result = task.next(); // 递归地执行 `next` function step() { // 如果没完的话 if (!result.done) { result = task.next(result.value); step(); } } // 开始处理 step(); }
- воплощать в жизнь
-
Добиваемся цели, пишем асинхронно синхронно
Присоединяйтесь к нам, чтобы заставить работать следующий код:
const asyncWork = new Promise((resolve, reject) => { setTimeout(() => resolve(5), 500) }) run(function* () { let value = yield asyncWork; console.log(value) value = yield value + 3; console.log(value) });
Здесь и предыдущий пример отличается от того,
yield
Возвращаемый результат может бытьpromise
if (result.value && typeof result.value.then === 'function') { result.value.then(d => { result = task.next(d) ... }) }
promise
, воплощать в жизньthen
функция, передать возвращаемый результат следующей итерацииnext(d)
Вот и все. Полный пример кода выглядит следующим образом:function run(taskDef) { // 创建并保存 iterator,留到后面使用 let task = taskDef(); let result = task.next(); // 递归地执行 `next` function step() { // 如果没完的话 if (!result.done) { if (result.value && typeof result.value.then === 'function') { result.value.then(d => { result = task.next(d) step(); }) } else { result = task.next(result.value); step(); } } } // 开始处理 step(); }
Посмотрите еще раз на это письмо:
run(function* () { let value = yield asyncWork; console.log(value) value = yield value + 3; console.log(value) });
Хотя второй
yield
к предыдущемуyield
Результат зависит, но его не нужно записывать как обратный вызов, он выглядит так же, как синхронизация, очень просто!
Эпилог
generator
произведеноiterator
, Можно использоватьnext
, К внешней функцииgenerator
данные могут передаваться черезthrow
Вставьте неправильный. они эквивалентныgenerator
Несколько коммуникационных окон открыты внутри и снаружи, что делает возможной явную асинхронность. мощныйredux-saga
также на основеgenerator
осуществленный. Есть ли другие способы играть? Все просто бросать кирпичи, чтобы привлечь Джейд, я не знаю, есть ли у вас другие способы игры?
если правильноgenerator
Происхождение не ясно, вы также можете взглянуть наздесь
Кроме того, эта статья была впервые опубликована вgithub, околоES6
серия статей. Помогите, если можетеstar
Да ладно, работу найти проще. Эй, ищу работу, правда-устал-ах! ! !