page - router events angular 6
Angular 4 es cada vez más lento a través del tiempo. (3)
Creo que el problema está en algún lugar dentro de ese mecanismo de suscripción en tus métodos de obtención.
(getProducts, getCategories etc.)
¿Cómo se crea el observable que se devuelve de las llamadas a su api-Service? Después de llamar a su api-Service, se suscribe al valor de retorno de esa llamada. ¿Es esa la respuesta original de la solicitud http? ¿O es un deber que te creaste?
En general, no necesita llamar para cancelar la suscripción en llamadas http en angular, como se describe aquí:
¿Necesita darse de baja de las llamadas http de Angular 2 para evitar la pérdida de memoria?
Pero en caso de que no esté pasando por ese observable de http original, sino que cree su propio abservable, es posible que deba limpiarlo usted mismo.
Tal vez usted puede publicar algún código de su api-Service? ¿Cómo creas esas promesas?
Otra cosa : ¿Te estás llamando a obtener el método de productos con un uuid diferente cada vez? Estaría escribiendo una nueva entrada en localStorage con cada uuid con el que llame a ese método
Tengo una aplicación angular 4.3.5 que se está ralentizando después de que se usa por un tiempo (~ 20 minutos).
Mi escenario es como:
- API de reposo y html / css / js angular estático ejecutándose en RaspberryPi B 3
- ~ 30 RaspberryPI B 3 que accede a la aplicación angular estática a través de Chromium (versiones 58 y 60)
Lo que ocurre:
- Las solicitudes HTTP de Angular se volvieron más lentas al pasar el tiempo. Ejemplo: de ~ 100 ms a ~ 2 segundos
Información Adicional:
- Si presiono F5 en Chromium, la aplicación Angular vuelve a la normalidad.
- Angular utiliza esta plantilla https://themeforest.net/item/primer-angular-2-material-design-admin-template/19228165
- Angular usa una aplicación Google Chrome / Chromium, que escribí, para la comunicación con Arduino a través del puerto serie (API de Chrome: chrome.runtime.sendMessage, chrome.runtime.connect y chrome.serial)
- El cliente, RaspberryPi, tiene recursos disponibles (CPU y memoria) cuando la aplicación se vuelve lenta
- La aplicación angular almacena casi nada en el navegador.
El componente que presenta el problema es el siguiente:
import { Component, OnInit, OnDestroy } from ''@angular/core'';
import { Router, ActivatedRoute } from ''@angular/router'';
import ''rxjs/add/operator/takeUntil'';
import { Subject } from ''rxjs/Subject'';
import { SweetAlertService } from ''ng2-cli-sweetalert2'';
import { ApiService } from ''.././api.service'';
import { NFCService } from ''.././nfc.service'';
@Component({
selector: ''app-menu'',
templateUrl: ''./menu.component.html'',
styleUrls: [''./menu.component.scss'']
})
export class MenuComponent implements OnInit, OnDestroy {
private ngUnsubscribe: Subject<void> = new Subject<void>();
cardId: string;
userId: string;
userName: string;
is_secure_bar: boolean = false;
requestInProgress = false;
userBalance: number = 0;
step: number = 1;
// showCheckout: boolean = false;
categories = new Array();
subcategories = new Array();
products = new Array();
cartItems = new Array();
countCartItems: number = 0;
totalCartValue: number = 0;
table_scroller;
table_scroller_height;
show_scroller_btns = false;
constructor(
public router: Router,
public route: ActivatedRoute,
private _nfcService: NFCService,
private _apiService: ApiService,
private _swal: SweetAlertService
) { }
ngOnInit() {
var account = localStorage.getItem(''account'');
if (account) {
// set variable to catch user data
// JSON.parse(
} else {
this.router.navigate([''login'']);
}
this.route.params
.takeUntil(this.ngUnsubscribe)
.subscribe(params => {
this.cardId = params.id;
this._apiService.getCardUser(params.id)
.takeUntil(this.ngUnsubscribe)
.subscribe(
response => {
// SUCCESS
this.userId = response.data[0].uuid;
this.userBalance = response.data[0].balance;
this.userName = response.data[0].name;
},
error => {
// ERROR
console.log(''Failed ;('', error);
}
);
});
this.getEvents()
.takeUntil(this.ngUnsubscribe)
.subscribe(
response => {
if (response.data[0].options.sales_auth_after_buy_is_required) {
this.is_secure_bar = true;
}
},
error => {
console.log(''Erro ao verificar Evento.'')
}
);
var categories = localStorage.getItem(''cache_categories'');
if (categories) {
this.categories = JSON.parse(categories);
} else {
// this.getCategories();
this.getCategoriesP()
}
}
//@felipe_todo
getEvents()
{
return this._apiService.getEvents();
//COMO FAZER LOGOUT ABAIXO
//localStorage.clear();
}
getCategories() {
this._apiService.getProductsCategories()
.takeUntil(this.ngUnsubscribe)
.subscribe(response => {
// SUCCESS
this.categories = response.data;
localStorage.setItem(''cache_categories'', JSON.stringify(this.categories));
}, error => {
// ERROR
console.log(''Failed ;('', error);
});
}
getCategoriesP() {
let categories;
this._apiService.getCategories()
.then(response => categories = response)
.then(() => {
this.categories = categories;
console.log(categories);
});
}
categorySelected(item) {
this.step = 2;
var subcategories = localStorage.getItem(''cache_subcategories_'' + item.uuid);
if (subcategories) {
this.subcategories = JSON.parse(subcategories);
} else {
// this.getSubcategories(item.uuid);
this.getSubcategoriesP(item.uuid);
}
}
getSubcategories(uuid) {
this._apiService.getProductsSubcategories(uuid)
.takeUntil(this.ngUnsubscribe)
.subscribe(response => {
// SUCCESS
this.subcategories = response.data;
localStorage.setItem(''cache_subcategories_'' + uuid, JSON.stringify(this.subcategories));
}, error => {
// ERROR
console.log(''Failed ;('', error);
});
}
getSubcategoriesP(uuid) {
let subcategories;
this._apiService.getSubcategories(uuid)
.then(response => subcategories = response)
.then(() => {
this.subcategories = subcategories;
console.log(subcategories);
});
}
subCategorySelected(item) {
this.step = 3;
var products = localStorage.getItem(''cache_products_'' + item.uuid);
if (products) {
this.products = JSON.parse(products);
} else {
// this.getProducts(item.uuid);
this.getProductsP(item.uuid);
}
}
getProducts(uuid) {
this._apiService.getProducts(uuid)
.takeUntil(this.ngUnsubscribe)
.subscribe(response => {
// SUCCESS
this.products = response.data;
localStorage.setItem(''cache_products_'' + uuid, JSON.stringify(this.products));
}, error => {
// ERROR
console.log(''Failed ;('', error);
});
}
getProductsP(uuid) {
let products;
this._apiService.getProductList(uuid)
.then(response => products = response)
.then(() => {
this.products = products;
console.log(products);
});
}
addToCard(product) {
var existentItems = this.cartItems.filter(function(item) {
return item.uuid === product.uuid
});
if (existentItems.length) {
existentItems[0].quantity += 1
} else {
product.quantity = 1;
this.cartItems.unshift(product);
}
let that = this;
this.calculateTotal();
setTimeout(function(){
that.setScroller();
}, 300);
}
removeProduct(index) {
let product = this.cartItems[index]
var existentItems = this.cartItems.filter(function(item) {
return item.uuid === product.uuid
});
if (existentItems.length) {
existentItems[0].quantity -= 1
if (existentItems[0].quantity == 0) {
this.cartItems.splice(index, 1);
}
} else {
product.quantity = 1;
this.cartItems.splice(index, 1);
}
this.calculateTotal();
let that = this;
setTimeout(function(){
if (that.table_scroller.offsetHeight < 270) {
that.show_scroller_btns = false;
}
}, 300);
}
calculateTotal() {
this.countCartItems = 0;
this.totalCartValue = 0;
var that = this;
this.cartItems.forEach(function(item) {
that.countCartItems += item.quantity;
that.totalCartValue += item.value * item.quantity;
});
}
backStep() {
if (this.step == 2) {
this.subcategories = new Array();
} else if (this.step == 3) {
this.products = new Array();
}
this.step--;
}
setScroller() {
if (this.cartItems.length) {
if (!this.table_scroller) {
this.table_scroller = document.querySelector(''#table-scroller'');
}else {
console.log(this.table_scroller.offsetHeight)
if (this.table_scroller.offsetHeight >= 270) {
this.show_scroller_btns = true;
} else {
this.show_scroller_btns = false;
}
}
}
}
scrollDown() {
(<HTMLElement>this.table_scroller).scrollTop = (<HTMLElement>this.table_scroller).scrollTop+50;
}
scrollUp() {
(<HTMLElement>this.table_scroller).scrollTop = (<HTMLElement>this.table_scroller).scrollTop-50;
}
confirmDebit() {
if (this.requestInProgress) return;
if (this.userBalance < this.totalCartValue) {
this._swal.error({ title: ''Salto Insuficiente'', text: ''Este cliente não possui saldo suficiente para essa operação.'' });
return;
}
this.requestInProgress = true;
var order = {
card_uuid: this.cardId,
event_uuid: ''c7b5bd69-c2b5-4226-b043-ccbf91be0ba8'',
products: this.cartItems
};
let is_secure_bar = this.is_secure_bar;
this._apiService.postOrder(order)
.takeUntil(this.ngUnsubscribe)
.subscribe(response => {
console.log(''Success'');
// this.router.navigate([''customer'', this.userId]);
let that = this;
this._swal.success({
title: ''Debito Efetuado'',
text: ''O débito foi efetuado com sucesso'',
showCancelButton: false,
confirmButtonText: ''OK'',
allowOutsideClick: false,
}).then(function(success) {
console.log("Clicked confirm");
if (is_secure_bar) {
that.logout();
} else {
that.router.navigate([''card'']);
}
});
this.requestInProgress = false;
}, error => {
// ERROR
console.log(''Request Failed ;('', error);
if (error.status !== 0) {
// TODO: Should display error message if available!
this._swal.error({ title: ''Erro'', text: ''Ocorreu um erro inesperado ao conectar-se ao servidor de acesso.'' });
} else {
this._swal.error({ title: ''Erro'', text: ''Não foi possível conectar-se ao servidor de acesso. Por favor verifique sua conexão.'' });
}
this.requestInProgress = false;
}
);
}
logout() {
let that = this;
localStorage.clear();
that.router.navigate([''login'']);
}
clearCheckout() {
this.cartItems = new Array();
this.calculateTotal();
this.router.navigate([''card'']);
}
ngOnDestroy() {
console.log(''uhul'')
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
Los métodos que presentan lentitud cada vez que accedemos al componente son:
getCategories () getSubcategories (uuid) getProducts (uuid) confirmDebit ()
Para propósitos de prueba, hemos creado una nueva versión para cada uno de estos métodos, esta vez trabajando con promesas:
getCategoriesP () getSubcategoriesP (uuid) getProductsP (uuid)
Independientemente de la versión del método llamado, ocurre el mismo problema.
No estoy seguro de si esto resolverá su problema de rendimiento, pero podría ser un paso en la dirección correcta.
Está creando una nueva Suscripción cada vez que cambia un parámetro de ruta, por lo que potencialmente podría terminar con una gran cantidad de suscripciones:
this.route.params
.takeUntil(this.ngUnsubscribe)
.subscribe(params => {
this.cardId = params.id;
this._apiService.getCardUser(params.id)
.takeUntil(this.ngUnsubscribe)
.subscribe(
response => {
// SUCCESS
this.userId = response.data[0].uuid;
this.userBalance = response.data[0].balance;
this.userName = response.data[0].name;
},
error => {
// ERROR
console.log(''Failed ;('', error);
}
);
});
Creo que es mejor que uses switchMap, de esa manera solo habrá 1 suscripción. Algo como:
this.route.params .switchMap(params => { this.cardId = params.id; return this._apiService.getCardUser(params.id) }) .takeUntil(this.ngUnsubscribe) .subscribe( response => { // SUCCESS this.userId = response.data[0].uuid; this.userBalance = response.data[0].balance; this.userName = response.data[0].name; }, error => { // ERROR console.log(''Failed ;('', error); } ); });
Si está ejecutando su aplicación como un SPA (aplicación de una sola página), esta puede ser una de las causas de la degradación del rendimiento a medida que transcurre el tiempo.
En SPA, el DOM se vuelve más pesado cada vez que el usuario visita una página nueva . Por lo tanto, tienes que trabajar en cómo mantener el DOM ligero.
A continuación se muestran las principales razones que encontré que mejoraron significativamente el rendimiento de mi aplicación.
Compruebe los puntos a continuación:
- Si ha usado el control de pestañas, cargue solo el contenido de pestañas activas y el contenido de otras pestañas no debería existir en el DOM.
- Si alguna ventana emergente se va a cargar, asegúrese de que carga el cuerpo solo cuando se abre.
- Los componentes comunes, como la
confirmation popup
y lamessage alert
deben definirse una vez y ser accesibles globalmente. - * ngPara aplicar con trackby ( https://netbasal.com/angular-2-improve-performance-with-trackby-cc147b5104e5 )
Una vez finalizado el servicio, llame a destruir en cualquier objeto: (a continuación se muestra el ejemplo de llamar a un servicio)
import { Subject } from ''rxjs/Subject''
import ''rxjs/add/operator/takeUntil'';
ngOnDestroy() {
this.ngUnsubscribe.next(true);
this.ngUnsubscribe.complete();
}
this.frameworkService.ExecuteDataSource().takeUntil(this.ngUnsubscribe).subscribe((data: any) => {
console.log(data);
});
Consulte los enlaces a continuación para obtener más detalles:
https://medium.com/paramsingh-66174/catalysing-your-angular-4-app-performance-9211979075f6