ジェネレーター関数を用いたJavaScriptでの効率的なデータストリーミング
- 作成日 2025.01.29
- その他

ジェネレーター関数は、JavaScriptで遅延評価やデータストリーミングを実現するための強力な機能です。この記事では、ジェネレーター関数の基本から応用までを詳しく取り上げ、効率的なデータ処理の方法を説明します。
目次
ジェネレーター関数の基本
function* simpleGenerator() {
yield 'データ1';
yield 'データ2';
yield 'データ3';
}
const gen = simpleGenerator();
console.log(gen.next()); // { value: 'データ1', done: false }
console.log(gen.next()); // { value: 'データ2', done: false }
console.log(gen.next()); // { value: 'データ3', done: false }
console.log(gen.next()); // { value: undefined, done: true }
無限ストリームの生成
function* infiniteCounter() {
let count = 0;
while (true) {
yield count++;
}
}
const counter = infiniteCounter();
console.log(counter.next().value); // 0
console.log(counter.next().value); // 1
console.log(counter.next().value); // 2
配列をジェネレーターで処理
function* arrayProcessor(array) {
for (const item of array) {
yield item;
}
}
const arrayGen = arrayProcessor([10, 20, 30]);
console.log(arrayGen.next().value); // 10
console.log(arrayGen.next().value); // 20
console.log(arrayGen.next().value); // 30
非同期ジェネレーター
async function* fetchData(urls) {
for (const url of urls) {
const response = await fetch(url);
const data = await response.json();
yield data;
}
}
const urls = ['https://api.example.com/1', 'https://api.example.com/2'];
(async () => {
for await (const data of fetchData(urls)) {
console.log(data);
}
})();
ジェネレーターとイテレーターの連携
function* nestedGenerators() {
yield* [1, 2, 3];
yield* [4, 5, 6];
}
const nestedGen = nestedGenerators();
console.log([...nestedGen]); // [1, 2, 3, 4, 5, 6]
ジェネレーターでデータ処理をパイプライン化
function* filterGenerator(numbers, predicate) {
for (const num of numbers) {
if (predicate(num)) {
yield num;
}
}
}
function* mapGenerator(numbers, mapper) {
for (const num of numbers) {
yield mapper(num);
}
}
const numbers = [1, 2, 3, 4, 5];
const filtered = filterGenerator(numbers, n => n % 2 === 0);
const mapped = mapGenerator(filtered, n => n * 10);
console.log([...mapped]); // [20, 40]
ジェネレーターを使ったカスタムデータストリーム
function* customDataStream(start, step, limit) {
let current = start;
while (current <= limit) {
yield current;
current += step;
}
}
const stream = customDataStream(0, 5, 20);
console.log([...stream]); // [0, 5, 10, 15, 20]
非同期ジェネレーターを用いたリアルタイム処理
async function* eventStream(eventSource) {
const queue = [];
eventSource.addEventListener('data', event => queue.push(event));
while (true) {
if (queue.length > 0) {
yield queue.shift();
} else {
await new Promise(resolve => setTimeout(resolve, 100));
}
}
}
ストリームAPIとジェネレーターの組み合わせ
async function* textStream(reader) {
const decoder = new TextDecoder();
let result;
while (!(result = await reader.read()).done) {
yield decoder.decode(result.value, { stream: true });
}
}
エラーハンドリングの追加
function* errorHandlingGenerator() {
try {
yield '正常なデータ';
throw new Error('エラー発生');
} catch (error) {
yield `エラー: ${error.message}`;
}
}
const genWithError = errorHandlingGenerator();
console.log(genWithError.next().value); // '正常なデータ'
console.log(genWithError.next().value); // 'エラー: エラー発生'
ジェネレーターの状態管理
function* statefulGenerator() {
let state = 0;
while (true) {
state += yield state;
}
}
const statefulGen = statefulGenerator();
console.log(statefulGen.next().value); // 0
console.log(statefulGen.next(5).value); // 5
console.log(statefulGen.next(10).value); // 15
まとめ
ジェネレーター関数は、効率的なデータストリーミングと柔軟なデータ処理を可能にします。シンプルな配列処理から非同期のリアルタイムデータ処理まで、多様なシナリオで活用できます。
-
前の記事
Dart Mapのkeyとvalueに指定した処理を実行する 2025.01.29
-
次の記事
Error: Rendered more hooks than during the previous render の解決方法 2025.01.29
コメントを書く