遍历器是ES6新增的一个属性,用于遍历得到一个数据的值,调用next方法可以依次拿到一个对象{value, done}
function idMaker() {
let index = 0;
next() {
return { value: index++, done: false }
}
}
const it = idMaker();
it.next(); //{value: 0, done: false}
it.next(); //{value: 1, done: false}
上面代码中, it是一个遍历器,调用next方法就可以同步得到一个对象,默认是同步执行
,如果是next是异步方法,会有什么结果呢,看下面的代码:
function idMaker() {
let index = 0;
return {
next: function() {
return new Promise(function (resolve, reject) {
setTimeout(() => {
resolve({ value: index++, done: false });
}, 1000);
});
}
};
}
const it = idMaker();
console.log(it.next()); // Promise
上面的代码中,next方法返回一个Promise对象,这违背了Iterator必须是异步的原则
,是无法达到目的的,这个如何解决呢?
我们可以把异步操作包装成Thunk函数或者Promise对象,等待返回真正的值,done属性是同步产生的
function idMaker() {
let index = 0;
return {
next: function() {
return {
value: new Promise(resolve => setTimeout(() => resolve(index++), 1000)),
done: false
};
}
};
}
const it = idMaker();
it.next().value.then(o => console.log(o)) // 0
it.next().value.then(o => console.log(o)) // 1
it.next().value.then(o => console.log(o)) // 2
上面的代码中,value的值是一个Promise对象,想要得到value的值,需要使用next
加then
的写法,不过这样写起来比较麻烦
1 异步遍历的接口
异步遍历器的的语法是调用遍历器的next方法,返回一个promise对象,可以通过then方法拿到value值
asyncIterator
.next()
.then(
({ value, done }) => /* ... */
);
对象的同步遍历器接口部署在Symbol.Iterator属性上面,而异步遍历器接口部署在Symbol.asyncIterator上,只要一个对象部署了异步遍历器,就需要对它进行异步遍历
创建一个异步遍历器:
const asyncIterable = createAsyncIterable(['a', 'b']);
const asyncIterator = asyncIterable[Symbol.asyncIterator]();
asyncIterator
.next()
.then(iterResult1 => {
console.log(iterResult1); // { value: 'a', done: false }
return asyncIterator.next();
})
.then(iterResult2 => {
console.log(iterResult2); // { value: 'b', done: false }
return asyncIterator.next();
})
.then(iterResult3 => {
console.log(iterResult3); // { value: undefined, done: true }
});
2 for await … of
我们直到,for…of可以遍历同步遍历器,现在说的for await … of 是遍历异步遍历器的方法,下面是一个伪代码示例:
async function f() {
for await (const x of createAsyncIterable(['a', 'b'])) {
console.log(x);
}
}
// a
// b
createAsyncIterator是一个异步遍历器接口对象,使用for…of的话,返回的是一个promise对象,使用await则可以处理这个promise对象,resolve之后,则会返给for…of循环
这个for await…of用于什么场景呢?下面举个例子,用于node环境中的stream接口
// 传统写法
function main(inputFilePath) {
const readStream = fs.createReadStream(
inputFilePath,
{ encoding: 'utf8', highWaterMark: 1024 }
);
readStream.on('data', (chunk) => {
console.log('>>> '+ chunk);
});
readStream.on('end', () => {
console.log('### DONE ###');
});
}
// 异步遍历器写法
async function main(inputFilePath) {
const readStream = fs.createReadStream(
inputFilePath,
{ encoding: 'utf8', highWaterMark: 1024 }
);
for await (const chunk of readStream) {
console.log('>>> '+chunk);
}
console.log('### DONE ###');
}