イテレータが来ている!JavaScriptの反復子とasynciterator



導入
この記事は、JavaScriptの2種類のイテレータを経由します.前者はしばらくJavaScriptの一部でした.後者はもうすぐES 2018です.
The iteration protocol JavaScriptはかなり基本的です.同期バージョンでは、私たちはnext でタプルを返す関数valuedone フラグ.例えば、
class SimpleIterable {
    next() {
        return { value: 3, done: true }
    }
}  
しかし、JavaScriptの多くの構造は「iterable」を期待していますnext 関数は必ずしも十分ではない.The for...of 構文はポイントの場合です.使いましょうfor...of ループをかけるSimpleIterable 対象:
const iter = new SimpleIterable()
for (const value of iter) {
    console.log('value = ' + value)
}
結果は以下の通りです:
C:\dev>node iter.js
C:\dev\iter.js:8
for (const value of iter) {
                    ^
TypeError: iter is not iterable
    at Object.<anonymous> (C:\dev\iter.js:8:21)

同期反復子
これは特殊関数を供給することで修正できます.この関数はシンボルで識別されます.Symbol.iterator . 我々のクラスにそれを加えることによって、我々は我々のiterableな仕事をすることができますfor...of :
class SimpleIterable {
    next() {
        return { value: 3, done: true }
    }

    [Symbol.iterator]() {
        return {
            next: () => this.next()
        }
    }
}

What is this [Symbol.iterator] syntax? Symbol.iterator is a unique identifier (see Symbol ). Putting it in square brackets makes it a computed property name. Computed properties were added in ES2015 (see Object initializer ). The documentation provides this simple example:

// Computed property names (ES2015)
var prop = 'foo';
var o = {
[prop]: 'hey',
['b' + 'ar']: 'there'
};
console.log(o) // { foo: 'hey', bar: 'there' }


もう一度やってみましょう
C:\dev>node iter.js
それは我々のエラーを修正しました、しかし、我々はまだ我々の価値を出力していません.如しfor...of 無視するvalue 一度それが真に遭遇done フラグ.
小さな値の配列を実際に繰り返すことによって、私たちの例をもう少し詳しく説明しましょう.我々が我々の配列の境界を越えるとき、我々value なるundefined アンドdone フラグはtrue :
class SimpleIterable {
    constructor() {
        this.index = 0
        this.values = [3,1,4]
    }

    next() {
        const value = this.values[this.index]
        const done = !(this.index in this.values)
        this.index += 1
        return { value, done }
    }

    [Symbol.iterator]() {
        return {
            next: () => this.next()
        }
    }   
}

const iter = new SimpleIterable()
for (const value of iter) {
    console.log('value = ' + value)
}
試してみましょう
C:\dev>node iter.js
value = 3
value = 1
value = 4
すごい、それは働いた!

非同期イテレータ
現在、JavaScriptのイテレータは同期していますがasynchronous iterators are coming in ES2018 . 彼らは既にノードの最近のバージョンで実装され、我々はそれらを使用して再生することができます--harmony-async-iteration フラグ.既存の例を非同期イテレータを使用して変更します.
const timer = () => setInterval(()=>console.log('tick'), 500)

class SimpleAsyncIterable {
    constructor() {
        this.index = 0
        this.values = [3,1,4]
    }

    next() {
        const value = this.values[this.index]
        const done = !(this.index in this.values)
        this.index += 1
        return new Promise(
            resolve=>setTimeout(()=>resolve({ value, done }), 1000))
    }

    [Symbol.asyncIterator]() {
        return {
            next: () => this.next()
        }
    }   
}

const main = async () => {
    const t = timer()

    const iter = new SimpleAsyncIterable()
    for await (const value of iter) {
        console.log('value = ' + value)
    }

    clearInterval(t)    
}

main()
何が違う?
  • 我々は、ちょうどAを返す代わりに、それを見ることができます{value, done} タプルnext メソッドは、a{value, done} タプル.
  • また、我々は現在、実装Symbol.asyncIterator の代わりに関数Symbol.iterator .
  • の構文for...of 非同期形式に変更されました.for await...of .
  • Since we can only use await in a function that is marked async, I've moved the driving code into an async main function. I've also added a timer so that we can clearly see that the for await...of construct is non-blocking.


    動作中の非同期iterableを見ましょう.
    C:\dev>node --harmony-async-iteration asyncIter.js
    tick
    value = 3
    tick
    tick
    value = 1
    tick
    tick
    value = 4
    tick
    tick
    
    すごい、それは働いた!私たちはfor await...of 用途Symbol.asyncIterator to await それぞれの約束.If the done フラグはfalseです.for await...ofvalue ループの各反復について.一旦それがAでオブジェクトを打つならばdone 真のフラグは、ループを終了します.

    It is possible to achieve a similar effect using synchronous iterators by returning a promise for the value attribute. However, done would not be asynchronous in that case.


    次の記事では、非同期発電機関数の詳細な検査を書きますfor await...of 構文.
    参考文献
  • for await...of
  • AsyncIterator
  • Iteration protocols
  • for...of
  • Symbol
  • Object initializer
  • Asynchronous iterators
  • ES2018: asynchronous iteration
  • 関連項目: