range() - Genereert een reeks getallen
range() is een for-achtige Creation Function die een opgegeven aantal opeenvolgende gehele getallen uitgeeft vanaf een opgegeven startwaarde.
Overzicht
range() geeft een reeks opeenvolgende gehele getallen uit als Observable door een startwaarde en het aantal gehele getallen op te geven. Het wordt gebruikt voor het genereren van opeenvolgende nummers en batchverwerking als een declaratieve manier om de traditionele for-statement te vervangen.
Handtekening:
function range(
start: number,
count?: number,
scheduler?: SchedulerLike
): Observable<number>Parameters:
start: De startwaarde (vanaf waar te beginnen met uitgeven)count: het aantal uit te geven waarden (weggelaten: van 0 tot minder danstart)scheduler: de scheduler om de waarden uit te geven (weggelaten: synchroon uitgeven)
Officiële Documentatie: 📘 RxJS Officieel: range()
Basisgebruik
Patroon 1: Startwaarde en aantal specificeren
Dit is het meest voorkomende gebruik.
import { range } from 'rxjs';
// Genereer 5 opeenvolgende nummers vanaf 1 (1, 2, 3, 4, 5)
range(1, 5).subscribe({
next: value => console.log('Waarde:', value),
complete: () => console.log('Voltooid')
});
// Output:
// Waarde: 1
// Waarde: 2
// Waarde: 3
// Waarde: 4
// Waarde: 5
// VoltooidPatroon 2: Opeenvolgende nummers vanaf 0
Door de startwaarde op 0 te zetten, kan een reeks nummers zoals een array-index worden gegenereerd.
import { range } from 'rxjs';
// 0 tot 10 opeenvolgende nummers (0, 1, 2, ..., 9)
range(0, 10).subscribe(console.log);
// Output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9Patroon 3: Starten met een negatief getal
Negatieve getallen kunnen ook worden gegenereerd.
import { range } from 'rxjs';
// 5 opeenvolgende nummers vanaf -3 (-3, -2, -1, 0, 1)
range(-3, 5).subscribe(console.log);
// Output: -3, -2, -1, 0, 1Belangrijke kenmerken
1. Synchrone emissie
Standaard geeft range() alle waarden synchroon uit bij abonnement.
import { range } from 'rxjs';
console.log('Voor abonnement');
range(1, 3).subscribe(value => console.log('Waarde:', value));
console.log('Na abonnement');
// Output:
// Voor abonnement
// Waarde: 1
// Waarde: 2
// Waarde: 3
// Na abonnement2. Voltooit onmiddellijk
Meldt complete onmiddellijk na het uitgeven van alle waarden.
import { range } from 'rxjs';
range(1, 3).subscribe({
next: val => console.log(val),
complete: () => console.log('Voltooid!')
});
// Output: 1, 2, 3, Voltooid!3. Equivalentie met for-statement
range(start, count) is equivalent aan de volgende for-statement.
// Imperatieve for-statement
for (let i = start; i < start + count; i++) {
console.log(i);
}
// Declaratieve range()
range(start, count).subscribe(console.log);Praktische use cases
1. Batchverwerking
Gebruikt om meerdere taken achtereenvolgens uit te voeren.
import { range, of, Observable, concatMap, delay, map } from 'rxjs';
// Functie om dataverwerking te simuleren
function processItem(index: number): Observable<string> {
return of(index).pipe(
delay(100), // Simuleer 100ms verwerkingstijd
map(i => `Resultaat van verwerking item ${i}`)
);
}
// Verwerk 10 items achtereenvolgens (1 seconde vertraging tussen elke verwerking)
range(1, 10).pipe(
concatMap(index =>
processItem(index).pipe(delay(1000))
)
).subscribe({
next: result => console.log(`Verwerking voltooid: ${result}`),
complete: () => console.log('Alle verwerking voltooid')
});
// Output:
// Verwerking voltooid: Resultaat van verwerking item 1 (na ongeveer 1,1 seconden)
// Verwerking voltooid: Resultaat van verwerking item 2 (na ongeveer 2,1 seconden)
// ...
// Verwerking voltooid: Resultaat van verwerking item 10 (na ongeveer 10,1 sec.)
// Alle verwerking voltooid2. Paginering
Haal meerdere pagina's met gegevens achtereenvolgens op.
import { range, of, Observable, concatMap, delay } from 'rxjs';
interface PageData {
page: number;
items: string[];
}
// Functie om het ophalen van paginagegevens te simuleren
function fetchPage(page: number): Observable<PageData> {
return of({
page,
items: [`Item${page}-1`, `Item${page}-2`, `Item${page}-3`]
}).pipe(
delay(500) // Simuleer API-aanroep
);
}
function fetchAllPages(totalPages: number) {
return range(1, totalPages).pipe(
concatMap(page => fetchPage(page))
);
}
fetchAllPages(5).subscribe({
next: (data: PageData) => console.log(`Pagina ${data.page}:`, data.items),
complete: () => console.log('Alle pagina\'s opgehaald')
});
// Output:
// Pagina 1: ['Item1-1', 'Item1-2', 'Item1-3']
// Pagina 2: ['Item2-1', 'Item2-2', 'Item2-3']
// Pagina 3: ['Item3-1', 'Item3-2', 'Item3-3']
// Pagina 4: ['Item4-1', 'Item4-2', 'Item4-3']
// Pagina 5: ['Item5-1', 'Item5-2', 'Item5-3']
// Alle pagina's opgehaald3. Array-indexen verwerken
Gebruik als een indexgebaseerde lus bij het verwerken van elk element van een array.
import { range, map } from 'rxjs';
const items = ['Appel', 'Banaan', 'Kers', 'Dadel', 'Vlierbes'];
range(0, items.length).pipe(
map(index => ({ index, item: items[index] }))
).subscribe(({ index, item }) => {
console.log(`[${index}] ${item}`);
});
// Output:
// [0] Appel
// [1] Banaan
// [2] Kers
// [3] Dadel
// [4] Vlierbes4. Testgegevens genereren
Handig voor het genereren van mock-gegevens voor unit tests.
import { range, map, toArray } from 'rxjs';
// Mock-gebruikersgegevens genereren
range(1, 100).pipe(
map(id => ({
id,
name: `Gebruiker${id}`,
email: `gebruiker${id}@example.com`
})),
toArray()
).subscribe(users => {
console.log(`${users.length} gebruikers gegenereerd`);
// Gebruik in testen
});5. Teller voor retry-verwerking
Controleert het aantal herhalingen bij een fout.
import { range, throwError, concat, of, Observable, mergeMap, delay, catchError, map, toArray } from 'rxjs';
// Functie om het ophalen van gegevens te simuleren (faalt willekeurig)
function fetchData(): Observable<string> {
const shouldFail = Math.random() > 0.7; // 30% kans op succes
return of(shouldFail).pipe(
delay(300),
mergeMap(fail =>
fail
? throwError(() => new Error('Gegevens ophalen mislukt'))
: of('Gegevens ophalen geslaagd')
)
);
}
function fetchWithRetry(maxRetries: number = 3) {
return concat(
range(0, maxRetries).pipe(
map(attempt => {
console.log(`Poging ${attempt + 1}/${maxRetries}`);
return fetchData().pipe(
catchError(error => {
if (attempt === maxRetries - 1) {
return throwError(() => new Error('Maximum aantal pogingen bereikt'));
}
return throwError(() => error);
}),
delay(Math.pow(2, attempt) * 1000) // Exponentiële backoff
);
}),
toArray()
)
);
}
fetchWithRetry().subscribe({
next: result => console.log('Resultaat:', result),
error: err => console.error('Fout:', err.message)
});
// Voorbeeldoutput:
// Poging 1/3
// Poging 2/3
// Resultaat: Gegevens ophalen geslaagdAsynchronisatie met Scheduler
Bij het verwerken van grote hoeveelheden gegevens is asynchrone uitvoering mogelijk door een scheduler op te geven.
import { range, asyncScheduler, observeOn } from 'rxjs';
console.log('Start');
// Asynchroon 1.000.000 nummers uitgeven
range(1, 1000000).pipe(
observeOn(asyncScheduler)
).subscribe({
next: val => {
if (val % 100000 === 0) {
console.log(`Voortgang: ${val}`);
}
},
complete: () => console.log('Voltooid')
});
console.log('Na abonnement (asynchroon, dus wordt onmiddellijk uitgevoerd)');
// Output:
// Start
// Na abonnement (asynchroon, dus wordt onmiddellijk uitgevoerd)
// Voortgang: 100000
// Voortgang: 200000
// ...
// VoltooidTIP
De Scheduler gebruiken:
- Blokkeer de UI niet bij het verwerken van grote hoeveelheden gegevens
- Tijdcontrole in testen (TestScheduler)
- Event loop controle in Node.js-omgeving
Voor meer informatie, zie Soorten Schedulers en hoe ze te gebruiken.
Vergelijking met andere Creation Functions
range() vs of()
import { range, of } from 'rxjs';
// range() - opeenvolgende gehele getallen
range(1, 3).subscribe(console.log);
// Output: 1, 2, 3
// of() - willekeurige waarden opsommen
of(1, 2, 3).subscribe(console.log);
// Output: 1, 2, 3
// Verschil: range() accepteert alleen opeenvolgende nummers, of() accepteert willekeurige waarden
of(1, 10, 100).subscribe(console.log);
// Output: 1, 10, 100 (niet mogelijk met range())range() vs from()
import { range, from } from 'rxjs';
// range() - opeenvolgende nummers genereren
range(1, 5).subscribe(console.log);
// Output: 1, 2, 3, 4, 5
// from() - genereren uit een array (moet array van tevoren maken)
from([1, 2, 3, 4, 5]).subscribe(console.log);
// Output: 1, 2, 3, 4, 5
// Voordeel van range(): geen voorafgaande toewijzing van arrays in geheugen
range(1, 1000000); // Geheugenefficiënt
from(Array.from({ length: 1000000 }, (_, i) => i + 1)); // Array gaat in geheugenrange() vs generate()
import { range, generate } from 'rxjs';
// range() - eenvoudige opeenvolgende nummering
range(1, 5).subscribe(console.log);
// Output: 1, 2, 3, 4, 5
// generate() - een complex voorbeeld van hetzelfde
generate(
1, // Initiële waarde
x => x <= 5, // Voortzettingsvoorwaarde
x => x + 1 // Iteratie
).subscribe(console.log);
// Output: 1, 2, 3, 4, 5
// Voordelen van generate(): complexe voorwaarde en statusbeheer
generate(
1,
x => x <= 100,
x => x * 2 // Verhoogt met factor 2
).subscribe(console.log);
// Output: 1, 2, 4, 8, 16, 32, 64
// (niet mogelijk met range())TIP
Selectiecriteria:
- Opeenvolgende nummers nodig →
range() - Willekeurige waarden opsommen →
of() - Bestaande array/Promise →
from() - Complexe voorwaarde/stap →
generate()
Prestatieoverwegingen
Omdat range() waarden synchroon uitgeeft, moet rekening worden gehouden met prestaties bij het genereren van grote aantallen waarden.
WARNING
Verwerken van grote hoeveelheden gegevens:
// ❌ Slecht voorbeeld: 1 miljoen waarden synchroon uitgeven (UI blokkeert)
range(1, 1000000).subscribe(console.log);
// ✅ Goed voorbeeld 1: asynchroon met scheduler
range(1, 1000000).pipe(
observeOn(asyncScheduler)
).subscribe(console.log);
// ✅ Goed voorbeeld 2: Splitsen door buffering
range(1, 1000000).pipe(
bufferCount(1000)
).subscribe(batch => console.log(`${batch.length} items verwerkt`));Kiezen tussen from() Array
import { range, from } from 'rxjs';
// Als u opeenvolgende nummers nodig heeft → range() is beknopter
range(0, 10).subscribe(console.log);
// Geen noodzaak om een array te maken en dan te converteren (inefficiënt)
from(Array.from({ length: 10 }, (_, i) => i)).subscribe(console.log);
// Als er een bestaande array is → gebruik from()
const existingArray = [5, 10, 15, 20];
from(existingArray).subscribe(console.log);Foutafhandeling
Hoewel range() zelf geen fouten uitgeeft, kunnen fouten optreden in de pipeline.
import { range, of, map, catchError } from 'rxjs';
range(1, 10).pipe(
map(n => {
if (n === 5) {
throw new Error('Fout bij 5');
}
return n * 2;
}),
catchError(error => {
console.error('Fout opgetreden:', error.message);
return of(-1); // Standaardwaarde retourneren
})
).subscribe(console.log);
// Output: 2, 4, 6, 8, -1Samenvatting
range() is een eenvoudige maar krachtige Creation Function die een reeks opeenvolgende gehele getallen produceert.
IMPORTANT
range() kenmerken:
- ✅ Ideaal voor het genereren van opeenvolgende nummers (alternatief voor for-statement)
- ✅ Handig voor batchverwerking, paginering, testgegevensgeneratie
- ✅ Geheugenefficiënt (geen voorafgaande creatie van arrays)
- ⚠️ Overweeg asynchroon voor grote hoeveelheden gegevens
- ⚠️ Gebruik
generate()voor complexe voorwaarden
Gerelateerde onderwerpen
- generate() - Generieke lusgeneratie
- of() - Willekeurige waarden opsommen
- from() - Converteren van array of Promise
- interval() - Periodiek waarden uitgeven