Call http request on destroy angular - javascript

http request is not executed
#HostListener('window:beforeunload')
async ngOnDestroy() {
await this.microSitioService.cancelarTransaccion(this.tarjetaCreditoService.seguimientoEtapa).then(() => {});
}
I need to execute an http request when the on destroy is executed

EDIT: Revised Answer
Ok, this is the format for when you want to make certain onDestroy is called - and also stop navigation away, using $event and preventDefault. I've also added how you can return a message to the browser to describe why nav was halted. You can use this to ensure that the http request is working as intended.
#HostListener('window:beforeunload', ['$event'])
async ngOnDestroy($event) {
if (this.componentSub) {
// handle unsubscriptions
this.componentSub.unsubscribe();
}
await this.microSitioService
.cancelarTransaccion(this.tarjetaCreditoService.seguimientoEtapa)
.then(() => {});
$event.preventDefault();
$event.returnValue = 'A message.';
}
Side Note: Have you included onDestroy as an implements on the class definition?
import { Component, OnDestroy, HostListener } from '#angular/core';
class MyComponent implements onDestroy {

If you are looking for an event that executes when the angular app is destroyed, you can use the PlatformRef which has an OnDestroy() callback
in main.ts
function doSomethingOnAppDestory() {
console.log('test');
}
platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {
// Ensure Angular destroys itself on hot reloads.
if (window['ngRef']) {
window['ngRef'].destroy();
}
window['ngRef'] = ref;
ref.onDestroy(doSomethingOnAppDestory);
// Otherwise, log the boot error
}).catch(err => console.error(err));
See the stackblitz demo

Related

Subject change detection not working on page load

Here is my app.component.ts (excerpt) -
export class AppComponent {
_subscription;
constructor(private themeService: ThemeService){
themeService.getDefaultTheme();
this._subscription = themeService.themeChange.subscribe((value) => {
//Some code
});
}
}
and theme.service.ts (excerpt) -
export class ThemeService {
themeChange: Subject<boolean> = new Subject<boolean>();
getDefaultTheme(){
this.changeTheme(true);
}
changeTheme(val:boolean){
//Some code
this.themeChange.next(val);
}
}
As app-root is my root component, the constructor in app.component.ts is called shortly after the initial page load. The constructor calls getDefaultTheme() which causes the Subject in theme.service.ts to emit an event. I am subscribing to that event back in the this._subscription ... part.
In short, on the initial page load, getDefaultTheme() should be called and the subscription should be handled as well.
But when I load the page, the getDefaultTheme() method is called but the subscription is not handled. I do not get any error at the compile time as well as in the run time.
I delayed the execution of getDefaultTheme() like
setTimeout(function(){
themeService.getDefaultTheme();
}, 5000);
Now the subscription was handled. I suspect that the event is not ready to be subscribed at the page load. How can I solve this?
It looks like you're emitting your subject before you've registered the subscription in the constructor. Swap over the call to your subject to be after you've registered the subscription.
export class AppComponent {
_subscription;
constructor(private themeService: ThemeService){
this._subscription = themeService.themeChange.subscribe((value) => {
//Some code
});
// After Subscription is listening
themeService.getDefaultTheme();
}
}
Subscribers to Subject could only receive notifications pushed to it's source after the subscription. Instead you could use ReplaySubject with buffer 1. It can "hold/buffer" the current value pushed to it and emit it immediately to future subscribers.
export class ThemeService {
themeChange: ReplaySubject<boolean> = new ReplaySubject<boolean>(1);
getDefaultTheme(){
this.changeTheme(true);
}
changeTheme(val:boolean){
//Some code
this.themeChange.next(val);
}
}
While BehaviorSubject is also a viable alternative, it requires a default value during initialization:
themeChange: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

Button click event is not reponding in Angular

In my .html file, I have the below code :-
Here the button Data Import appears....
<button mat-menu-item (click)="download()">
<mat-icon>cloud_download</mat-icon>
<span>Data Import</span>
</button>
In the component.ts file :-
Here I have defined the functioned to be called after the button is clicked::
constructor(
private downloadService: DownloadService
)
download(){
this.downloadService.getDownload();
}
In downloadservice.ts file :-
Here the service has been created which is going to call the api /Download at the backend.
export class DownloadService {
etext : String;
baseUrl: string = environment.apiUrl + '/Download';
constructor(private http: HttpClient) { }
getDownload() {
return this.http.get(this.baseUrl);
this.etext="The operation has been done";
}
}
When I click on the Data Import button ..nothing happens and no event is generated.
1- The second line will not be executed as first statement has a return keyword:
return this.http.get(this.baseUrl);
this.etext="The operation has been done";
2- As Martin ÄŒuka commented below, you need to subscribe the Observable being returned by httpclient.
this.downloadService.getDownload().subscribe(resp => { // do whatever });
Nothing happens because httpClient is returning Observable you need to subscribe to it.
Add subsribe to your service
this.downloadService.getDownload().subscribe();
as for the line
this.etext="The operation has been done";
compiler will say to you it's unreachable nevertheless the real problem is in missing subscribe
export class Component {
constructor(private downloadService: DownloadService){}
download(){
this.downloadService.getDownload().subscribe(
() => {
// success code
},
(error) => {
// error code
}
);
}
}}
I think that the http request is fired.
However, you don't know when it finished because you are not subscribing to the Observable that the http.get returns.
component.ts
export class Component {
constructor(private downloadService: DownloadService){}
download(){
this.downloadService.getDownload().subscribe(
() => {
// success code
},
(error) => {
// error code
}
);
}
}
Be careful with subscription, you have to unsubscribe when the subscription finish.
https://blog.angularindepth.com/the-best-way-to-unsubscribe-rxjs-observable-in-the-angular-applications-d8f9aa42f6a0

aurelia aurelia-http-client jsonp

I try to query an api which is not the same origin with the aurelia-http-client.
My code pretty simple :
import {HttpClient} from 'aurelia-http-client';
export class App {
constructor(){
console.log("constructor called");
let url = 'http://localhost:8081/all';
let client = new HttpClient();
client
.jsonp(url)
.then(data => {
console.log("datas");
console.log(data);
});
}
}
Nothing happens, I can see in network that the url is called, my api engine logs an entry but I never enter in the "then" of the "promise"...
What's wrong ?
Update :
I give you some screenshots with catch
code source
browser result
With JQuery on the same machine no problems.
After reading this post other jsonp case I try to add the work "callback" and now it works !!!
so call jsonp(url, 'callback')
client.jsonp(url, 'callback')
Thanks...
This may not be a direct answer but just a suggestion, I would rather use the aurelia API as I found it more consistent and stable.
just add it as plugin in you main :
.plugin('aurelia-api', config => {
config.registerEndpoint('github', 'https://api.github.com/');
});
and use it as:
import {Endpoint} from 'aurelia-api':
#autoinject
export class Users{
constructor(private githubEndpoint){
}
activate() {
return this.githubEndpoint.find('users')
.then(users => this.users = users);
}
}
Source: https://aurelia-api.spoonx.org/Quick%20start.html

Angular 2 app base initialization

How can I make basic initialization of my data in app. For example if user logged in and press F5 I need to request current user data from server before all queries starts like get user order etc. In Angular 1 we have .run() directive for this case. How can I solve this problem?
There are several ways to do that:
You could execute some requests before bootstrapping your Angular2 application. Such first requests could rely what you save into the local / session storage.
var injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
var http = injector.get(Http);
http.get('/userdetails').map(res => res.json())
.subscribe(data => {
bootstrap(AppComponent, [
HTTP_PROVIDERS
provide('userDetails', { useValue: data })
]);
});
See this question for more details:
How to bootstrap an Angular 2 application asynchronously
You could extend the HTTP request to transparently get these data when requests are actually executed. This would be a lazy approach.
#Injectable()
export class CustomHttp extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, userDetailsService: UserDetailsService) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
console.log('request...');
return this.userDetailsService.getUserDetails().flatMap((userDetails) => {
return super.request(url, options);
});
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
console.log('get...');
return this.userDetailsService.getUserDetails().flatMap((userDetails) => {
return super.get(url, options);
});
}
}
implement the UserDetailsDetails this way:
export class UserDetailsService {
constructor(private http:Http) {
}
getUserDetails() {
if (this.userDetails) {
return Observable.of(this.userDetails);
} else {
return this.http.get(...)
.map(...)
.do(data => {
this.userDetails = data;
// Store in local storage or session storage
});
}
}
and register this CustomHttp class this way:
bootstrap(AppComponent, [HTTP_PROVIDERS,
UserDetailsService,
new Provider(Http, {
useFactory: (backend: XHRBackend,
defaultOptions: RequestOptions,
userDetailsService: UserDetailsService) => new CustomHttp(backend, defaultOptions, userDetailsService),
deps: [XHRBackend, RequestOptions, UserDetailsService]
})
]);
See these questions for more details:
Angular 2 - How to get Observable.throw globally
Cache custom component content in ionic 2
Things could also be done at the level of the router outlet if you use routing. It's possible to implement a custom router-outlet that checks security / user details when a route is activated. I think that it's a little further from your need...
See this question for more details:
Angular 2 Cancelling Route Navigation on UnAuthenticate
You could fetch the current user data before you call Angular2's bootstrap(...)
You could also fire an event (using an Observable for example) to notify other that the logged-in user is now known and initiate further requests only after this event was received.

How can check offline and online in angular

I have been getting an error from the service call when browse is in offline mode. How can check off-line mode and want to block my service call when the browser is the offline mode?
I suggest you to use Offline.js
they have templates and other stuff to work with .
you can check out their documentation and see how it works .
it gets you the current state of the connection by returning the "up" or "down" result , or you can bind and event to it and use it across you'r application .
this is what they say about their library :
Offline.js is a library to automatically alert your users when they've lost internet connectivity, like Gmail.
It captures AJAX requests which were made while the connection was down, and remakes them when it's back up, so your app reacts perfectly.
It has a number of beautiful themes and requires no configuration.
good luck and have fun.
Check for navigator.onLineand based on this value decide whether to send request or not.
if (navigator.onLine) {
$http.get('url').success(function() {});
}
else {
// no req
}
Angular way:
Use $q service - A service that helps you run functions asynchronously, and use their return values (or exceptions) when they are done processing. https://docs.angularjs.org/api/ng/service/$q
The best way that I would know would be to intercept the HTTP handler, if its a 401 / 501/ etc. then to handle it according
angular.module('myApp', ['myApp.services'],
function ($httpProvider) {
var interceptor = ['$rootScope', '$q', function ($rootScope, $q) {
function success(response) {
return response;
}
function error(response) {
var status = response.status; // error code
if ((status >= 400) && (status < 500)) {
$rootScope.broadcast("AuthError", status);
return;
}
if ( (status >= 500) && (status < 600) ) {
$rootScope.broadcast("ServerError", status);
return;
}
// otherwise
return $q.reject(response);
}
return function (promise) {
return promise.then(success, error);
}
}];
$httpProvider.responseInterceptors.push(interceptor);
then in your code that listens for the on of, just add in
$rootScope.$on("ServerError", someServerErrorFunction);
Source: How to detect when online/offline status changes
Online/offline detection cannot be 100% accurately decided because network status can vary for a number of reasons.
Still, if you want an implementation of the same with Angular+NGRX, You can find more details here.
https://hackernoon.com/using-angular-to-detect-network-connection-status-onlineoffline
import { Component, OnDestroy, OnInit, VERSION } from '#angular/core';
import { fromEvent, merge, of, Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
networkStatus: boolean = false;
networkStatus$: Subscription = Subscription.EMPTY;
constructor() {}
ngOnInit(): void {
this.checkNetworkStatus();
}
ngOnDestroy(): void {
this.networkStatus$.unsubscribe();
}
checkNetworkStatus() {
this.networkStatus = navigator.onLine;
this.networkStatus$ = merge(
of(null),
fromEvent(window, 'online'),
fromEvent(window, 'offline')
)
.pipe(map(() => navigator.onLine))
.subscribe(status => {
console.log('status', status);
this.networkStatus = status;
});
}
}
You can see the demo here.
or check the code here
Happy coding!!! 🎉🎉🎉

Categories

Resources