私は中規模のAngularアプリケーションを使用しており、いくつかの理由により、私の本番環境に対して実行すると、いくつかの分度器テストがタイムアウトします。
分度器が非同期タスクを待機しているため、タイムアウトが発生することはほぼ間違いありません。私はゾーンについて知っており、ngZoneから長時間実行されている非同期タスクをすべて保持しようとしました( FAQ に従って)が、何らかの理由で分度器はまだタイムアウトしています。
何かを見逃した可能性がありますが、問題のデバッグ方法がわかりません。 コード分度器のどの部分が待機しているかを確認する方法はありますか?
NgZoneは、実行中のマイクロタスクまたはマクロタスクがあるかどうかを判別するための関数のみを公開しますが、どちらがどれであるかはわかりません。
EDIT:分度器が示すようなタイムアウトエラーの典型的な例:
失敗:非同期の待機中にタイムアウトしましたAngularタスクが11秒後に完了するのを待っています。これは、現在のページがAngularアプリケーションではないためである可能性があります。 FAQ詳しくは https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular
ロケーター付きの要素を待つ間-ロケーター:By(css selector、[data-e2e = 'scroll-to-offer'])
要素はページに存在します(手動で確認しました)が、分度器はまだタイムアウトします。
同様の問題がありました Testability は不安定で、pendingMacroTasks
がいくつかあるということしか知りませんでした。これらのタスクをローカライズするのは確かに少しトリッキーです(コードベース全体を調べてsetTimeout
を探すことはありません)。
しかし、最終的にはなんとかこれを行うことができました。
最初にできることは、ChromeでDev Toolsを開き、_Ctrl+O
_を押し、zone.jsと入力してEnter
を押します。
これにより、zone.jsソースファイル(TypeScriptではなく、まだ何か)が開きます。
内側zone.js_Zone.prototype.runTask
_を探し、このメソッド内にブレークポイントを置きます。
アプリケーションのロード後にブレークポイントを有効にします。そうしないと、何度もヒットします。
Testabilityが安定していない場合、おそらくそれ自体を再スケジュールするrepetitiveマクロタスクがあることを意味します。少なくともそれは私の場合でした。
この場合、アプリケーションがロードされた後、ブレークポイントはX回ごとにヒットします。
ブレークポイントに到達したら、_task.callback.[[FunctionLocation]]
_に移動すると、(おそらく)setTimeout
またはsetInterval
に移動します。
修正するには outside of Angular zone 。
これにはZone.jsコードの微調整が含まれますが、より永続的なデバッグ情報が提供されます。
node_modules/zone.js/dist/zone.js
_に移動します。function Zone(parent, zoneSpec)
this._tasks = {}
_let counter = 0
__Zone.prototype.scheduleTask
_を探し、this._updateTaskCount(task,1)
の呼び出しの直前に次の行を追加します。
_task.id = counter++;
this._tasks[task.id] = task;
_
_Zone.prototype.scheduleTask
_を探し、this._updateTaskCount(task,-1)
の呼び出しの直前に次の行を追加します。
_delete this._tasks[task.id]
_
上記の調整を行ったとすると、次のような保留中のタスクにいつでもアクセスできます。
_tasks = Object.values(window.getAllAngularTestabilities()[0]._ngZone._inner._tasks)
_
テスト容易性の状態に影響する保留中のすべてのマクロタスクを取得するには:
_tasks.filter(t => t.type === 'macroTask' && t._state === 'scheduled')
_
その後、前のソリューションと同様に、_.callback.[[FunctionLocation]]
_を確認し、Angularゾーンの外で実行して修正します。
分度器の非同期タスクを追跡する特定の方法はありません。あなたがするかもしれないことは、どの非同期タスクがフローをブロックしているのかを調査することです。テストする場合、デバッグには2つの主な手がかりがあります。アプリコードの非同期タスクとテストの非同期タスクです。
テストで、ジャスミンのようなものを使用している場合、jasmine.DEFAULT_TIMEOUT_INTERVAL;
?
とにかく、起動時とコールバック時にすべての非同期タスクのロギングを開始する以外に、これをデバッグするためのより良いオプションはありません。
ベルコフ、
あなたが提供する機能を使用してタスクリストを取得するには、本当にあなたの助けが必要です。
import 'zone.js/dist/task-tracking'
を追加しました。 AppModule.tsのコンストラクタメソッドにpolyfills.ts
以下のコードを追加します。エラーCannot find name 'moduleInstance'.
がスローされます
// app.module.ts
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);
可能であれば、実際の例を教えてください。それはあなたの大きな助けになります。
ありがとうございました、
ジグネシュラヴァル
CC:@ hodossy-szabolcs
JeBは way を提案する素晴らしい仕事をしました(いくつかの解決策は何もないよりはましです)。実際、保留中のタスクのリストを取得する方法がありますパッチを適用せずにzone.js
ファイル。 angularソース: https://github.com/angular/angular/blob/master/packages/core/src/zone/ng_zone.ts #L134
方法は次のとおりです。
node_modules/zone.js/dist/task-tracking.js
の後にzone.js
ファイルをインポート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);