<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Итераторы и генераторы on JSFlow</title><link>https://jsflow.ru/docs/iterators/</link><description>Recent content in Итераторы и генераторы on JSFlow</description><generator>Hugo</generator><language>ru</language><atom:link href="https://jsflow.ru/docs/iterators/index.xml" rel="self" type="application/rss+xml"/><item><title>Итерируемые объекты и протокол итерации</title><link>https://jsflow.ru/docs/iterators/iterables/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://jsflow.ru/docs/iterators/iterables/</guid><description>&lt;h1 id="итерируемые-объекты-и-протокол-итерации"&gt;
 Итерируемые объекты и протокол итерации
 &lt;a class="anchor" href="#%d0%b8%d1%82%d0%b5%d1%80%d0%b8%d1%80%d1%83%d0%b5%d0%bc%d1%8b%d0%b5-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d1%8b-%d0%b8-%d0%bf%d1%80%d0%be%d1%82%d0%be%d0%ba%d0%be%d0%bb-%d0%b8%d1%82%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d0%b8"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Итерируемый объект&lt;/strong&gt; (iterable) предоставляет метод &lt;code&gt;[Symbol.iterator]()&lt;/code&gt;, возвращающий &lt;strong&gt;итератор&lt;/strong&gt; — объект с методом &lt;code&gt;next()&lt;/code&gt;, который выдаёт значения &lt;code&gt;{ value, done }&lt;/code&gt;. Протокол итерации лежит в основе &lt;code&gt;for...of&lt;/code&gt;, spread и части API коллекций; понимание его нужно до &lt;a href="https://jsflow.ru/docs/iterators/generators/"&gt;генераторов&lt;/a&gt; и &lt;a href="https://jsflow.ru/docs/iterators/async-iterators/"&gt;async-итераторов&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="итератор-вручную"&gt;
 Итератор вручную
 &lt;a class="anchor" href="#%d0%b8%d1%82%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80-%d0%b2%d1%80%d1%83%d1%87%d0%bd%d1%83%d1%8e"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Минимальный итератор для трёх кодов статуса доставки:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createStatusIterator&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;statuses&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;index&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;statuses&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;statuses&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;index&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;], &lt;span style="color:#a6e22e"&gt;done&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;undefined&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;done&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;it&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createStatusIterator&lt;/span&gt;([&lt;span style="color:#e6db74"&gt;&amp;#39;pending&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;shipped&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;delivered&amp;#39;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;it&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// { value: &amp;#39;pending&amp;#39;, done: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;it&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// { value: &amp;#39;shipped&amp;#39;, done: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;it&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// { value: &amp;#39;delivered&amp;#39;, done: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;it&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// { value: undefined, done: true }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Когда &lt;code&gt;done: true&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt; обычно &lt;code&gt;undefined&lt;/code&gt; и дальнейшие вызовы &lt;code&gt;next()&lt;/code&gt; не обязаны менять состояние.&lt;/p&gt;</description></item><item><title>Генераторы</title><link>https://jsflow.ru/docs/iterators/generators/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://jsflow.ru/docs/iterators/generators/</guid><description>&lt;h1 id="генераторы"&gt;
 Генераторы
 &lt;a class="anchor" href="#%d0%b3%d0%b5%d0%bd%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Генератор&lt;/strong&gt; — особая разновидность итератора: функция &lt;code&gt;function*&lt;/code&gt; при вызове возвращает объект-генератор с методами &lt;code&gt;next&lt;/code&gt;, &lt;code&gt;return&lt;/code&gt; и &lt;code&gt;throw&lt;/code&gt;. Ключевое слово &lt;code&gt;yield&lt;/code&gt; приостанавливает выполнение и отдаёт значение наружу. Генераторы удобны для ленивых потоков данных — постраничная загрузка товаров, обход вложенных категорий, пошаговая сборка чекаута.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="объявление-и-первый-next"&gt;
 Объявление и первый &lt;code&gt;next()&lt;/code&gt;
 &lt;a class="anchor" href="#%d0%be%d0%b1%d1%8a%d1%8f%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b8-%d0%bf%d0%b5%d1%80%d0%b2%d1%8b%d0%b9-next"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;orderIdSequence&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;prefix&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;prefix&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;-&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;String(&lt;span style="color:#a6e22e"&gt;n&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;padStart&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ids&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;orderIdSequence&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;ord&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ids&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// { value: &amp;#39;ord-0001&amp;#39;, done: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ids&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// { value: &amp;#39;ord-0002&amp;#39;, done: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Тело генератора не выполняется при вызове &lt;code&gt;orderIdSequence('ord')&lt;/code&gt; — только при первом &lt;code&gt;next()&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Асинхронные итераторы</title><link>https://jsflow.ru/docs/iterators/async-iterators/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://jsflow.ru/docs/iterators/async-iterators/</guid><description>&lt;h1 id="асинхронные-итераторы"&gt;
 Асинхронные итераторы
 &lt;a class="anchor" href="#%d0%b0%d1%81%d0%b8%d0%bd%d1%85%d1%80%d0%be%d0%bd%d0%bd%d1%8b%d0%b5-%d0%b8%d1%82%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Асинхронный итератор&lt;/strong&gt; реализует &lt;code&gt;[Symbol.asyncIterator]()&lt;/code&gt; и возвращает объект, у которого &lt;code&gt;next()&lt;/code&gt; отдаёт &lt;strong&gt;Promise&lt;/strong&gt; на &lt;code&gt;{ value, done }&lt;/code&gt;. Цикл &lt;code&gt;for await...of&lt;/code&gt; и &lt;strong&gt;async-генераторы&lt;/strong&gt; &lt;code&gt;async function*&lt;/code&gt; — основной способ последовательно обрабатывать данные из &lt;a href="https://jsflow.ru/docs/async/promises/"&gt;промисов&lt;/a&gt; и &lt;a href="https://jsflow.ru/docs/network/fetch/"&gt;fetch&lt;/a&gt; без ручной цепочки &lt;code&gt;then&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="for-awaitof"&gt;
 &lt;code&gt;for await...of&lt;/code&gt;
 &lt;a class="anchor" href="#for-awaitof"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Перебирает async iterable — каждый шаг ждёт разрешения Promise:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;loadOrderStatuses&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ids&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;results&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ids&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`/api/orders/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;results&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;push&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;results&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Когда источник уже async iterable:&lt;/p&gt;</description></item></channel></rss>