SpeedOf.Me API - Angular Integration
Note: Angular requires a build process (TypeScript compilation, bundling). This page shows the source code. See the README for setup instructions.
1. Type Definitions (speedofme.d.ts)
interface SpeedTestResult {
download: number;
upload: number;
latency: number;
jitter: number;
testServer?: string;
ip_address?: string;
hostname?: string;
}
interface SpeedTestProgress {
testType: 'download' | 'upload';
currentSpeed: number;
percentComplete: number;
passNumber: number;
}
interface SomApi {
account: string;
domainName: string;
config: {
sustainTime: number;
testServerEnabled: boolean;
userInfoEnabled: boolean;
latencyTestEnabled: boolean;
uploadTestEnabled: boolean;
};
startTest: () => void;
onTestCompleted: (result: SpeedTestResult) => void;
onProgress: (progress: SpeedTestProgress) => void;
onError: (error: { code: number; message: string }) => void;
}
declare var SomApi: SomApi;
2. Speed Test Service (speed-test.service.ts)
import { Injectable, NgZone } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
export type TestStatus = 'idle' | 'running' | 'completed' | 'error';
@Injectable({ providedIn: 'root' })
export class SpeedTestService {
private statusSubject = new BehaviorSubject<TestStatus>('idle');
private resultSubject = new BehaviorSubject<SpeedTestResult | null>(null);
private progressSubject = new BehaviorSubject<SpeedTestProgress | null>(null);
private errorSubject = new BehaviorSubject<{ code: number; message: string } | null>(null);
status$ = this.statusSubject.asObservable();
result$ = this.resultSubject.asObservable();
progress$ = this.progressSubject.asObservable();
error$ = this.errorSubject.asObservable();
constructor(private ngZone: NgZone) {
this.initializeApi();
}
private initializeApi(): void {
SomApi.account = 'YOUR_API_KEY';
SomApi.domainName = 'your-domain.com';
SomApi.config.sustainTime = 4;
SomApi.onTestCompleted = (result) => {
this.ngZone.run(() => {
this.resultSubject.next(result);
this.progressSubject.next(null);
this.statusSubject.next('completed');
});
};
SomApi.onProgress = (progress) => {
this.ngZone.run(() => {
this.progressSubject.next(progress);
});
};
SomApi.onError = (error) => {
this.ngZone.run(() => {
this.errorSubject.next(error);
this.statusSubject.next('error');
});
};
}
startTest(): void {
this.statusSubject.next('running');
this.resultSubject.next(null);
this.errorSubject.next(null);
SomApi.startTest();
}
}
3. Speed Test Component (speed-test.component.ts)
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SpeedTestService } from '../../services/speed-test.service';
@Component({
selector: 'app-speed-test',
standalone: true,
imports: [CommonModule],
template: `
<div class="speed-test">
<button
(click)="startTest()"
[disabled]="(status$ | async) === 'running'"
>
{{ (status$ | async) === 'running' ? 'Testing...' : 'Start Test' }}
</button>
<div *ngIf="progress$ | async as progress" class="progress">
<p>{{ progress.testType | titlecase }} Test</p>
<div class="progress-bar">
<div [style.width.%]="progress.percentComplete"></div>
</div>
<p>{{ progress.currentSpeed.toFixed(2) }} Mbps</p>
</div>
<div *ngIf="result$ | async as result" class="results">
<p>Download: {{ result.download }} Mbps</p>
<p>Upload: {{ result.upload }} Mbps</p>
<p>Latency: {{ result.latency }} ms</p>
<p>Jitter: {{ result.jitter }} ms</p>
</div>
<div *ngIf="error$ | async as error" class="error">
Error {{ error.code }}: {{ error.message }}
</div>
</div>
`
})
export class SpeedTestComponent {
status$ = this.speedTestService.status$;
result$ = this.speedTestService.result$;
progress$ = this.speedTestService.progress$;
error$ = this.speedTestService.error$;
constructor(private speedTestService: SpeedTestService) {}
startTest(): void {
this.speedTestService.startTest();
}
}
4. Add Script to index.html
<!DOCTYPE html>
<html>
<head>
<script src="https://speedof.me/api/api.js"></script>
</head>
<body>
<app-root></app-root>
</body>
</html>