Exp*_*lls 1 javascript arrays ecmascript-6 ecmascript-7
我正在创建一个异步迭代的数组(为了好玩).这很好用:
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);
}
}();
Run Code Online (Sandbox Code Playgroud)
然而,这打印出来0...1...2是因为我正在跟踪我自己的当前计数器并将其初始化为x.
有没有办法让当前的迭代器值在数组内部?我还需要能够正确地确定done价值.
我想你不希望计数器在你的数组内部,而是你的迭代器.在方法中使用局部变量:
[Symbol.iterator]() {
var x = 0;
return {
next: () => {
let promise = new Promise(resolve =>
setTimeout(() => resolve(this[x++]), 1000)
);
return {done: x >= this.length, value: promise};
}
};
}
Run Code Online (Sandbox Code Playgroud)
编写迭代器的最简单方法是使用生成器函数:
[Symbol.iterator]*() {
for (var x = 0; x < this.length; x++)
yield new Promise(resolve =>
setTimeout(() => resolve(this[x]), 1000)
);
}
Run Code Online (Sandbox Code Playgroud)
这也将照顾正确的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;
}
Run Code Online (Sandbox Code Playgroud)