I want to calculate download and upload internet speed in Angular.
Request to API will not be the best solution, because if the server itself is slowed down from the load, the result will be incorrect.
Perhaps there are solutions for Angular, which use special sites for this (e.g. speedtest.net).
Any ideas?
What is the internet speed?
Everyone want to download faster and faster, and also upload files even faster. But what does it mean? When you download or upload something, you and a server are communicating in a particular way.Both of you have an internet connection, but in most cases, your is slower than the server's connection. To understand this, simply follow this logic:
You are playing some video games with other thousands of user. Your (and the other player connection) can send and receive 20 units per second. The server can send up to 2 millions unit per second. In this way everyone is happy and is online. If the server could just send 20 units per second, everyone would've lagged, or even worst (Like package loss).
So, to answer what internet speed is, is the time that takes from a request sent to you, to travel to the server, have a response, and then turn it back to you. Of course if the server is down or has finished his units space to dedicate to you, your request would be delayed, but this is how the internet works.
When you download or stream a film, it happens the same thing: You are requesting new chunk every time you finished to download/stream a small part.
Let's talk about some number
Time is counted, in the internet, in milliseconds. If you just open a terminal and do a simple ping www.stackoverflow.com
you will have something like that :
Reply from 151.101.1.69: bytes=32 time=36ms TTL=56
Reply from 151.101.1.69: bytes=32 time=36ms TTL=56
Reply from 151.101.1.69: bytes=32 time=36ms TTL=56
Reply from 151.101.1.69: bytes=32 time=36ms TTL=56
that time=36ms
is the time passed between you sending the ping request, and the request backing to you.
In the end
I hope to have cleared everything, measuring time, in the web, is intended like this way:
- Start counting
- Send a request
- ...
- Wait..
- ...
- Request turned back
- Stop Counting
** But my question is: Can I do it in angular?**
The answer is.. Kinda. Probably there are better ways to do that, but few months ago I wanted to do it as well, and I came up with that idea.
Let's assume we have a service that do a request :
export class MyService{
constructor(
private http: Http
)
public sendRequest(){
return this.http.get(...something);
}
}
Our main component will have the service injection and will count the times passed :
export class MyComponent{
public timePassed: any;
constructor(
private service: MyService
)
ngOnInit(): void{
const startingTime = new Date().getTime();
this.service.sendRequest()
.subscribe( res => {
this.timePassed = ((new Date() - startingTime).getTime())/1000;
});
}
}
Now in your timePassed
variable you will have the time that the request took.
As I said, the time can change due to your connection being slow, or because the server's connection is slow.
You always have to think at internet speed like two people talking to each other. Always. It makes no sense otherwise to talk to speed if you can't relate yours to someone else speed.
If you want to use third party API, there are some dedicated speed test websites, which also provide API access. E.g:
You can checkout related SO answers here.
OR
If you want to implement it yourself in Angular, you can checkout my repository. I did this sometime ago to test download speed: angular-speed-test.
I used Angular HttpClient progress events to track transfer of data and calculated speed based on that.
service code:
import { Injectable } from "@angular/core";
import { HttpClient, HttpRequest } from "@angular/common/http";
@Injectable({
providedIn: "root"
})
export class FileDownloaderService {
url: string = "some file path for download";
constructor(private http: HttpClient) {}
download() {
const req = new HttpRequest("GET", this.url, {
responseType: "blob",
reportProgress: true
});
return this.http.request(req);
}
}
component:
import { Component } from "@angular/core";
import { HttpClient, HttpEventType, HttpResponse } from "@angular/common/http";
import { FileDownloaderService } from "./file-downloader.service";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
constructor(
private http: HttpClient,
private downloader: FileDownloaderService
) {}
percentDone: number;
startTime: any;
endTime: any;
currTime: any;
prevTime: any;
speed: number = 0;
bytesReceied: number = 0;
oldbytes: number = 0;
unit: string = "Mbps";
download() {
this.downloader.download().subscribe(event => {
if (event.type === HttpEventType.DownloadProgress) {
//tracking percent received and how much time has passed
this.percentDone = Math.round((100 * event.loaded) / event.total);
this.currTime = new Date().getTime();
//setting start time
if (this.percentDone === 0) {
this.startTime = new Date().getTime();
this.prevTime = this.startTime;
}
//tracking how much data is received
this.bytesReceied = event.loaded / 1000000;
//calculating download speed per percent data received
this.speed =
(this.bytesReceied - this.oldbytes) /
((this.currTime - this.prevTime) / 1000);
if (this.speed < 1) {
this.unit = "Kbps";
this.speed *= 1000;
} else this.unit = "Mbps";
//updating previous values
this.prevTime = this.currTime;
this.oldbytes = this.bytesReceied;
//calculating avg download speed
if (this.percentDone === 100) {
this.endTime = new Date().getTime();
let duration = (this.endTime - this.startTime) / 1000;
let mbps = event.total / duration / 1000000;
if (mbps < 1) {
this.speed = event.total / duration / 1000;
this.unit = "Kbps";
} else {
this.speed = mbps;
this.unit = "Mbps";
}
}
}
//download file
else if (event instanceof HttpResponse) {
var res: any = event.body;
var url = window.URL.createObjectURL(res);
var a = document.createElement("a");
document.body.appendChild(a);
a.setAttribute("style", "display: none");
a.href = url;
a.download = "SpeedTest_32MB.dat";
a.click();
window.URL.revokeObjectURL(url);
a.remove();
console.log("File is completely downloaded!");
}
});
}
}
Demo
I think this is totally independent of Angular. Furthermore using a connection to a server seems to be the only way to perform the desired measurement. All speed test pages I know of are using very powerful, well-connected servers from which they receive packages of known sizes (or upload to them).
You can try using this library for measuring connection speed with Netflix's fast.com. If you don't want to use a library for some reason, the implementation should be easy enough to write on your own :-) .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With