Task Scheduling

To track tasks, we have to revisit how setTimeout() is monkey patched to modify the way Zone’s are tracked.

要跟踪任务,我们必须看下 setTimeout() 的猴子补丁如何修改被跟踪的 zone。

  1. // 保存setTimeout的原始引用
  2. let originalSetTimeout = window.setTimeout;
  3. // 使用在 zone 中包含回调的函数覆盖API。
  4. window.setTimeout = function(callback, delay) {
  5. // 对当前 zone 使用scheduleTask API。
  6. Zone.current.scheduleMacroTask(
  7. // 调试信息
  8. 'setTimeout',
  9. // 回调需要在当前 zone 执行。
  10. callback,
  11. // 可选数据,如任务是否重复。
  12. null,
  13. // 默认计划行为
  14. (task) => {
  15. return originalSetTimeout(
  16. // Use the task invoke method, so that the task can
  17. // call callback in the correct zone.
  18. task.invoke,
  19. // original delay information
  20. delay
  21. );
  22. });
  23. }

使用示例:

  1. // Create a logging zone
  2. let logZone = Zone.current.fork({
  3. onScheduleTask: function(parentZoneDelegate, currentZone,
  4. targetZone, task) {
  5. // Print when async tasks are scheduled
  6. console.log('Schedule', task.source);
  7. return parentZoneDelegate.scheduleTask(targetZone, task);
  8. },
  9. onInvokeTask: function(parentZoneDelegate, currentZone,
  10. targetZone, task, applyThis, applyArgs) {
  11. // Print when async tasks are invoked
  12. console.log('Invoke', task.source);
  13. return parentZoneDelegate.invokeTask(
  14. targetZone, applyThis, applyArgs);
  15. }
  16. });
  17. console.log('start');
  18. logZone.run(() => {
  19. setTimeout(() => null, 0);
  20. });
  21. console.log('end');

输出结果

  1. start
  2. Schedule setTimeout
  3. end
  4. Invoke setTimeout

关键点:

  • All APIs which schedule tasks use Zone.prototype.scheduleTask() instead of Zone.prototype.wrap().
  • Tasks use Zone.prototype.runGuarded() for callback execution, hence they handle all of the errors.
  • Tasks are intercepted using invokeTask() whereas zones are intercepted using invoke().