• Task Scheduling

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