I'd suggest you to use Angular HTTP Module. It's Angular native and as such easier to integrate with other parts of the application.
You could then use a container (like RxJS ReplaySubject
with buffer 1) to cache/hold the values from the HTTP request and the subsequent FileReader
's onload
callback.
Note: since this is all asynchronous, any statements that directly depend on the result from the HTTP request must be inside the subscription. See here for more info on how async data works.
app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { HttpClientModule } from "@angular/common/http";
import { AppComponent } from "./app.component";
import { DataService } from './data.service';
@NgModule({
imports: [BrowserModule, FormsModule, HttpClientModule],
declarations: [AppComponent],
bootstrap: [AppComponent],
providers: [DataService]
})
export class AppModule {}
data.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http"; // <-- import `HttpClient`
import { Observable, ReplaySubject } from 'rxjs';
@Injectable()
export class DataService {
private fileSource: ReplaySubject<any> = new ReplaySubject<any>(1);
public file$: Observable<any> = this.fileSource.asObservable();
constructor(private http: HttpClient) { // <-- inject `HttpClient`
this.getFile(); // <-- trigger file fetch here
}
getFile(): void {
this.http.get('/path/to/local/image/file', { responseType: "blob" }).subscribe({ // <-- add `responseType`
next: (response: any) => {
const reader = new FileReader();
reader.onload = (event) => { // <-- arrow function
this.fileSource.next(event.target.result); // <-- push to the `ReplaySubject`
}
reader.readAsDataURL(response) // <-- should NOT be `this.response`
},
error: (error: any) => {
// handle error
}
});
}
}
app.component.ts
import { Component, OnInit, OnDestroy } from "@angular/core";
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
import { DataService } from "./data.service";
@Component({ ... })
export class AppComponent implements OnInit, OnDestroy {
close$ = new Subject<any>();
file: any;
constructor(private _data: DataService) { }
ngOnInit() {
this._data.file$.pipe(
takeUntil(this.close$)
).subscribe({
next: (file: any) => {
this.file = file;
// other statements that depend on `this.file`
}
});
}
ngOnDestroy() {
this.close$.next(); // <-- close open subscriptions
}
}
Update
- Add
responseType
to GET request
- Working example: Stackblitz