本篇介紹 ES2018 (ES9) 提供的 async iterators (非同步迭代器)。
在 ES2015 (ES6) 引入了 iterator interface,spec 的定義如下:必須要有 next()
,其回傳值必須符合 IteratorResult
interface
下面是 IteratorResult
interface 的定義,需有以下 property:
done
:Boolean 值
next()
呼叫的結果狀態done
為 true
done
為 false
value
:任何值
done
為 false
,則 value
為當前迭代元素值 (iteration element value)done
為 true
,則 value
則為 iterator 的回傳值 (若沒有回傳值則 value
為 undefined
)例如:建立一個 generator 函數,呼叫該 generator 函數時,會回傳 Generator
物件,此物件實作了 Iterable
interface 和 Iterator
interface,所以也可說是建立新的 iterator 物件,接著就可呼叫 iterator 上的 next()
:
function* generatorFunc() {
yield 'first';
yield 'second';
}
let iterator = generatorFunc();
console.log(iterator);
// generatorFunc {<suspended>}
console.log(iterator.next());
// {value: "first", done: false}
console.log(iterator.next());
// {value: "second", done: false}
console.log(iterator.next());
// {value: undefined, done: true}
但過去的 iterator 只適合處理同步資料,需要 I/O 存取的資料都會透過 event-based 或 streaming 非同步 API 來處理,但 iterator 不能處理非同步資料。
若是 promise 的 iterator 也不行處理,因為只能非同步處理 value
,但不能非同步處理 done
狀態,也就是說下一個值根本就還沒確定,怎麼會知道有沒有 done
呢?而且 value
可能也還沒拿到。
為了給非同步資料提供通用的存取 protocol,此提案引入了 AsyncIterator
interface、async iteration statement ( for-await-of
) 和 async generator function。
AsyncIterator
interface 和 Iterable
interface 很像,只是將 next()
回傳的值變為 IteratorResult
物件的 Promise
,spec 的定義如下:
所以原本同步的 iterator 可以直接從 next()
回傳的 IteratorResult
物件拿到 value
和 done
:
const { value, done } = syncIterator.next();
console.log(value);
console.log(done);
而非同步 iterator 因為是 Promise
,所以可以這樣處理:
asyncIterator.next()
.then(({ value, done }) => {
console.log(value);
console.log(done);
});