1

我正在创建一个异步迭代的数组(为了好玩)。这工作正常:

class AsyncArray extends Array {
    constructor() {
        super();
        this.x = 0;
    }

    [Symbol.iterator]() {
        return {
            next: () => {
                let promise = new Promise(resolve => setTimeout(
                    () => resolve(this.x++), 1000)
                );
                return {done: this.x >= this.length, value: promise};
            }
        };
    }
}

async () => {
    for (let x of AsyncArray.of(1, 2, 3)) {
        let value = await x;
        console.log(value);
    }
}();

但是,这会打印出来,0...1...2因为我自己跟踪当前计数器并将其初始化为x.

有什么方法可以获取数组内部的当前迭代器值?我还需要能够正确确定该done值。

4

1 回答 1

5

我猜你不想要你的数组内部的计数器,而是你的迭代器。为此在方法中使用局部变量:

[Symbol.iterator]() {
    var x = 0;
    return {
        next: () => {
            let promise = new Promise(resolve =>
                setTimeout(() => resolve(this[x++]), 1000)
            );
            return {done: x >= this.length, value: promise};
        }
    };
}

编写迭代器的最简单方法是使用生成器函数:

[Symbol.iterator]*() {
    for (var x = 0; x < this.length; x++)
         yield new Promise(resolve =>
             setTimeout(() => resolve(this[x]), 1000)
         );
}

这也将处理正确的done值(并且不会“ return”用 解决的承诺undefined)。


完全避免在局部变量或实例属性中跟踪状态的替代方法是使用标准数组迭代器:

[Symbol.iterator]() {
    var vals = super[Symbol.iterator]();
    var it = Object.create(Object.getPrototypeOf(vals)); // an array iterator
    it.next = () => {
        var res = vals.next();
        if (!res.done)
            return {done: false, value: new Promise(resolve =>
                setTimeout(() => resolve(res.value), 1000)
            )};
        return res;
    };
    return it;
}
于 2015-06-30T12:42:25.303 回答