Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

228
Views
Ejecute ngrx/effect fuera de la zona de Angular para evitar el tiempo de espera en Protractor

Acabo de empezar a escribir pruebas e2e para mi aplicación y tengo problemas de tiempo de espera con Protractor y ngrx/effects.

Tengo el siguiente efecto enviando una acción cada par de minutos:

 @Effect() setSessionTimer$ = this.actions$ .ofType(Auth.ActionTypes.SET_SECONDS_LEFT) .map(toPayload) .switchMap(secondsLeft => Observable.concat( Observable.timer((secondsLeft - 60) * 1000).map(_ => new Auth.SessionExpiringAction(60)), Observable.timer(60 * 1000).map(_ => new Auth.SessionExpiredAction()) ));

Intentar ejecutar una prueba de transportador hace que la prueba se agote con el siguiente error, ya que Angular no es estable.

Error: se agotó el tiempo de espera para que finalicen las tareas angulares asincrónicas después de 11 segundos. Esto puede deberse a que la página actual no es una aplicación de Angular. Consulte las preguntas frecuentes para obtener más detalles: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular Mientras espera el elemento con el localizador - Localizador: Por (css selector, . barra de herramientas-título)

De acuerdo con este problema ( https://github.com/angular/protractor/issues/3349 ), necesito usar NgZone para ejecutar un intervalo Observable fuera de Angular. Probé diferentes combinaciones de this.ngZone.runOutsideAngular() pero nada funcionó y las pruebas siguen agotando el tiempo de espera.

Por ejemplo esto no funciona:

 @Effect() setSessionTimer$ = this.actions$ .ofType(Auth.ActionTypes.SET_SECONDS_LEFT) .map(toPayload) .switchMap(secondsLeft => this.ngZone.runOutsideAngular(() => Observable.concat( Observable.timer((secondsLeft - 60) * 1000).map(_ => new Auth.SessionExpiringAction(60)), Observable.timer(60 * 1000).map(_ => new Auth.SessionExpiredAction()) )));

No tengo idea de cómo ejecutar el efecto fuera de Angular. ¿Alguien ha probado con éxito e2e su aplicación ngrx?

about 4 years ago · Santiago Trujillo
2 answers
Answer question

0

La solución es programar el temporizador observable para que se ejecute fuera de NgZone y luego volver a ingresar a la zona cuando ocurra algo interesante.

Primero, necesitará dos funciones de utilidad que envuelvan cualquier planificador y hagan que el efecto entre o salga de la zona:

 import { Subscription } from 'rxjs/Subscription'; import { Scheduler } from 'rxjs/Scheduler'; import { NgZone } from '@angular/core'; class LeaveZoneSchduler { constructor(private zone: NgZone, private scheduler: Scheduler) { } schedule(...args: any[]): Subscription { return this.zone.runOutsideAngular(() => this.scheduler.schedule.apply(this.scheduler, args) ); } } class EnterZoneScheduler { constructor(private zone: NgZone, private scheduler: Scheduler) { } schedule(...args: any[]): Subscription { return this.zone.run(() => this.scheduler.schedule.apply(this.scheduler, args) ); } } export function leaveZone(zone: NgZone, scheduler: Scheduler): Scheduler { return new LeaveZoneSchduler(zone, scheduler) as any; } export function enterZone(zone: NgZone, scheduler: Scheduler): Scheduler { return new EnterZoneScheduler(zone, scheduler) as any; }

Luego, al usar un programador (como asap o async ), puede hacer que una transmisión ingrese o salga de la zona:

 import { async } from 'rxjs/scheduler/async'; import { enterZone, leaveZone } from './util'; actions$.ofType('[Light] Turn On') .bufferTime(300, leaveZone(this.ngZone, async)) .filter(messages => messages.length > 0) .observeOn(enterZone(this.ngZone, async))

Tenga en cuenta que la mayoría de los operadores basados en el tiempo (como bufferTime , debounceTime , Observable.timer , etc.) ya aceptan un planificador alternativo. Solo necesita observeOn para volver a ingresar a la zona cuando sucede algo interesante.

about 4 years ago · Santiago Trujillo Report

0

Para Angular 6 y RxJS 6 use el siguiente código:

 import { SchedulerLike, Subscription } from 'rxjs' import { NgZone } from '@angular/core' class LeaveZoneScheduler implements SchedulerLike { constructor(private zone: NgZone, private scheduler: SchedulerLike) { } schedule(...args: any[]): Subscription { return this.zone.runOutsideAngular(() => this.scheduler.schedule.apply(this.scheduler, args) ) } now (): number { return this.scheduler.now() } } class EnterZoneScheduler implements SchedulerLike { constructor(private zone: NgZone, private scheduler: SchedulerLike) { } schedule(...args: any[]): Subscription { return this.zone.run(() => this.scheduler.schedule.apply(this.scheduler, args) ) } now (): number { return this.scheduler.now() } } export function leaveZone(zone: NgZone, scheduler: SchedulerLike): SchedulerLike { return new LeaveZoneScheduler(zone, scheduler) } export function enterZone(zone: NgZone, scheduler: SchedulerLike): SchedulerLike { return new EnterZoneScheduler(zone, scheduler) }

El efecto debería verse así:

 import { asyncScheduler, queueScheduler } from 'rxjs' import { filter, observeOn, bufferTime } from 'rxjs/operators' import { enterZone, leaveZone } from './util'; actions$.ofType('[Light] Turn On') .pipe( bufferTime(300, leaveZone(this.ngZone, asyncScheduler)), filter(messages => messages.length > 0), observeOn(enterZone(this.ngZone, queueScheduler)), )
about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!