如何跟踪量角器等待的异步任务?

mag*_*tic 13 protractor zonejs angular

我有一个中等大小的Angular应用程序,由于某些原因,我的一些量角器测试在我的实时生产环境中运行时超时.

我很确定超时发生是因为量角器等待某个异步任务.我知道区域,我试图将所有长时间运行的异步任务保留在ngZone之外(根据常见问题解答),但由于某些原因,量角器仍然超时.

我可能错过了一些东西,但我不知道如何调试问题.有没有办法找出代码量角器的哪一部分正在等待?

NgZone只公开函数来确定是否有微任务或macrotasks运行,但不告诉我哪一个.

编辑:量角器显示的这种超时错误的典型示例:

失败:超时等待异步Angular任务在11秒后完成.这可能是因为当前页面不是Angular应用程序.有关详细信息,请参阅常见问题解答:https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular

在等待带定位器的元素时 - 定位器:By(css选择器,[data-e2e ='scroll-to-offer'])

该元素存在于页面上(我已经手动验证过),但量角器仍然超时.

JeB*_*JeB 18

我有一个类似的问题,可测性是不稳定的,我所知道的是我有一些pendingMacroTasks.本地化这些任务确实有点棘手(你不会通过整个代码库来寻找setTimeout).
但是我最终设法做到了这一点.

相对简单的解决方案

您可以做的第一件事是在Chrome中打开您的开发工具,按Ctrl+O,输入zone.js然后按Enter.
这将打开zone.js源文件(不是Typescript,还有东西).
zone.js中查找Zone.prototype.runTask并在此方法中放置一个断点.在加载应用程序后
启用断点,否则会被击中太多次.

如果您的可测试性不稳定,则可能意味着您有一些重新安排自己的重复宏任务.至少那是我的情况.
如果是这种情况,则在加载应用程序后,断点将每X次触发一次.

一旦断点被​​击中,转到task.callback.[[FunctionLocation]]这将带你(最有可能)一些setTimeoutsetInterval.
要修复它,请在Angular区域外运行它.

有点棘手的解决方案

这涉及调整Zone.js代码,但为您提供更持久的调试信息.

  1. 去吧node_modules/zone.js/dist/zone.js.
  2. 寻找Zone的构造函数: function Zone(parent, zoneSpec)
  3. 在里面添加以下内容: this._tasks = {}
  4. 全局范围内添加计数器变量:let counter = 0
  5. Zone.prototype.scheduleTask在调用之前查找并添加以下内容this._updateTaskCount(task,1):

    task.id = counter++;
    this._tasks[task.id] = task;
    
    Run Code Online (Sandbox Code Playgroud)
  6. Zone.prototype.scheduleTask在调用之前查找并添加以下内容this._updateTaskCount(task,-1):

    delete this._tasks[task.id]
    
    Run Code Online (Sandbox Code Playgroud)
  7. 重新编译应用程序并运行它

假设您进行了上述调整,您可以随时访问待处理的任务,如下所示:

tasks = Object.values(window.getAllAngularTestabilities()[0]._ngZone._inner._tasks)
Run Code Online (Sandbox Code Playgroud)

要获取影响可测试性状态的所有待处理宏任务:

tasks.filter(t => t.type === 'macroTask' && t._state === 'scheduled')
Run Code Online (Sandbox Code Playgroud)

之后,与之前的解决方案类似,.callback.[[FunctionLocation]]通过在Angular区域外运行来检查并修复.


Sta*_*kov 12

JeB 很好地提出了他的方法(一些解决方案总比没有好)。事实上,有一种方法可以在不修补zone.js文件的情况下获取待处理任务列表。我在查看角度来源时得到这个想法:https : //github.com/angular/angular/blob/master/packages/core/src/zone/ng_zone.ts#L134

以下是如何:

  1. 导入node_modules/zone.js/dist/task-tracking.js文件后zone.js
  2. 然后在您的代码中获取NgZone实例并使用它
import * as _ from "lodash";
...
const ngZone = moduleInstance.injector.get(NgZone);
setInterval(() => {
    var taskTrackingZone = (<any>ngZone)._inner.getZoneWith("TaskTrackingZone");
    if (!taskTrackingZone) {
        throw new Error("'TaskTrackingZone' zone not found! Have you loaded 'node_modules/zone.js/dist/task-tracking.js'?");
    }
    var tasks: any[] = taskTrackingZone._properties.TaskTrackingZone.getTasksFor("macroTask");
    tasks = _.clone(tasks);
    if (_.size(tasks) > 0) {
        console.log("ZONE pending tasks=", tasks);
    }
}, 1000);

Run Code Online (Sandbox Code Playgroud)

示例放在这里:https : //stackblitz.com/edit/zonejs-pending-tasks

这个怎么运作:


Fra*_*sco 1

没有特定的方法来跟踪量角器的异步任务。您可能要做的就是调查哪些异步任务可能会阻塞您的流程。如果您正在测试,则有 2 个主要调试线索:应用程序代码中的异步任务和测试中的异步任务。

在你的测试中,如果你使用像 Jasmine 这样的东西,你是否尝试过类似改变的东西jasmine.DEFAULT_TIMEOUT_INTERVAL;

不管怎样,除了在启动和回调时开始记录所有异步任务之外,我没有看到更好的选项来调试它。