在Angular区域之外运行ngrx/effect以防止在量角器中超时 [英] Run ngrx/effect outside of Angular's zone to prevent timeout in Protractor

查看:85
本文介绍了在Angular区域之外运行ngrx/effect以防止在量角器中超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始为我的应用程序编写e2e测试,并且遇到了量角器和ngrx/effects超时的问题.

I just started to write e2e tests for my app and am running into timeout problems with Protractor and ngrx/effects.

我每隔几分钟发送一次动作具有以下效果:

I have the following effect dispatching an action every couple of minutes:

@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())
        ));

由于Angular不稳定,尝试运行量角器测试会导致测试超时并显示以下错误.

Trying to run a Protractor test causes the test to timeout with the following error, since Angular is not stable.

失败:等待异步Angular任务完成时超时 11秒后.这可能是因为当前页面不是 角度应用.请参阅常见问题解答以了解更多详细信息: https://github.com/angular/protractor /blob/master/docs/timeouts.md#waiting-for-angular 在等待带有定位符的元素时-定位符:By(css选择器, .toolbar-title)

Failed: Timed out waiting for asynchronous Angular tasks to finish after 11 seconds. This may be because the current page is not an Angular application. Please see the FAQ for more details: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular While waiting for element with locator - Locator: By(css selector, .toolbar-title)

根据此问题( https://github.com/angular/protractor/issues/3349 )我需要使用NgZone在Angular之外运行一个Observable间隔.我尝试了this.ngZone.runOutsideAngular()的不同组合,但是没有任何效果,并且测试还在不断超时.

According to this issue (https://github.com/angular/protractor/issues/3349) I need to use NgZone to run an interval Observable outside of Angular. I have tried different combinations of this.ngZone.runOutsideAngular() but nothing worked and the tests keep on timing out.

例如,这不起作用:

@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())
        )));

我不知道如何在Angular之外运行效果. 有没有人成功e2e测试了他们的ngrx应用程序?

I have no idea how to run the effect outside Angular. Has anybody successfully e2e tested their ngrx app?

推荐答案

解决方案是安排可观察的计时器安排在NgZone之外运行,然后在发生有趣的事情时重新进入区域.

The solution is to schedule the timer observable to run outside of NgZone and then re-enter the zone when something interesting occurs.

首先,您将需要两个实用程序功能,这些功能可以包装任何调度程序并导致效果进入或离开区域:

First you are going to need two utility functions that wrap any scheduler and cause the effect to enter or leave the zone:

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;
}

然后使用调度程序(例如asapasync),可以使流进入或离开区域:

Then using a scheduler (like asap or async) you can cause a stream to enter or leave the zone:

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))

请注意,大多数基于时间的运算符(例如bufferTimedebounceTimeObservable.timer等)已经接受了备用调度程序.发生有趣的事情时,您只需observeOn重新进入区域.

Note that most of the time-based operators (like bufferTime, debounceTime, Observable.timer, etc) already accept an alternative scheduler. You only need observeOn to re-enter the zone when something interesting happens.

这篇关于在Angular区域之外运行ngrx/effect以防止在量角器中超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆