我正在学习ngZone如何在Angular中工作。我知道它正在对标准异步操作(例如 setTimeout)进行猴子修补。
但谁在打猴子补丁?zone.js 库或 ngZone 中的 Angular 本身?如果您可以在源代码中显示它发生的特定位置,那就太好了。
Angular 在 zone.js 中运行区域,zone.js 提供了一个带有修补 API 的范围。
您可以自己使用zone.run(...)
Angular 并获得修补 API 的所有效果。
另请参阅https://github.com/angular/zone.js/
修补计时器的代码 https://github.com/angular/zone.js/blob/master/lib/common/timers.ts#L22
区域库必须在浏览器和服务器端项目中工作。所以它比仅仅修补全局函数要复杂一些。
Zone 不仅修补全局 API,还修补广播的事件对象。修补是通过完成的Zone.__load_patch
,您可以看到这些模块中正在修补的内容。
https://github.com/angular/zone.js/blob/master/lib/browser/browser.ts
https://github.com/angular/zone.js/blob/master/lib/node/node.ts
https://github.com/angular/zone.js/blob/master/lib/rxjs/rxjs.ts
这显然不是一个简单的过程。我确信仍有一些区域尚未修补的边缘情况。
猴子补丁由 Zone.js 完成。在 ng_zone.ts 中,加载了 zone.ts,它创建了根区域以及猴子补丁 API。
NGZone 只是分叉了一个名为“ angular ”的子区域,并在区域规范中提供回调。在这些回调中,它发出在 application_ref.ts 中进一步订阅的事件,并启动更改检测。
Monkey Patching:这是通过使用 2 个参数调用Zone.__load_patch()函数来完成的。第一个参数是猴子补丁 API 的标识符,第二个是补丁函数,它在执行时会用重新定义的版本替换实际的浏览器 API。
现在,这只是冰山一角。实际的魔法是通过调用utils.ts 的patchMethod()来完成的。对于 set/clearTimeOut 情况,这是在此处完成的。
在patchMethod() 中,原始api 保存在局部变量即委托中,并返回保存在timers.ts内的setNative 变量中的相同api。
有关完整的工作流程,您可以参考以下文章。