【发布时间】:2018-01-31 08:04:06
【问题描述】:
我将 $http 替换为 Fetch API,并将 $q 替换为 Promise API。因此,Angular 不再运行摘要循环,因此 UI 没有呈现。为了解决这个问题,我尝试了 Zone.js,这似乎部分解决了我们的问题。不幸的是,它的 API 在 0.6 中完全改变了,所以我们使用 legacy 0.5.15。
现在是实际问题。
当刷新页面时,Angular 会像预期的那样配置和引导应用程序。在这个阶段,我正在初始化区域并用区域和$rootScope.$digest() 装饰$rootScope.apply。现在,当我在状态/路由(使用 ui-router)之间转换时,一切都按预期工作,但是当完全刷新时,会出现竞争条件,并且区域/摘要无法正确运行。我不知道如何解决它。
我在angular.run() 块中有以下代码:
console.log('Zone setup begin');
const scopePrototype = $rootScope.constructor.prototype;
const originalApply = scopePrototype.$apply;
const zoneOptions = {
afterTask: function afterTask() {
try {
$rootScope.$digest();
} catch (e) {
$exceptionHandler(e);
throw e;
}
}
};
scopePrototype.$apply = function $applyFn() : void {
const scope = this;
const applyArgs = arguments;
window.zone.fork(zoneOptions).run(() => {
originalApply.apply(scope, applyArgs);
console.log('Zone + $digest run!');
});
};
console.log('Zone setup end');
您可以在上面看到,当区域初始化开始、结束和运行时(+ Angular 摘要循环),我登录到控制台。在我通过 Fetch API 获取数据的控制器中,我添加了一个 console.log('Data fetched!');,这样我就知道何时获取了数据。
现在控制台中的输出:
使用 ui-router 进行状态转换 (完美运行)
请注意,摘要在最后运行。
Zone setup begin
Zone setup end
Zone + $digest run!
Zone + $digest run!
Zone + $digest run!
Zone + $digest run!
Data fetched!
Zone + $digest run!
状态/路线完全刷新 (最终不运行)
Zone setup begin
Zone setup end
Zone + $digest run!
Zone + $digest run!
Zone + $digest run!
Zone + $digest run!
Data fetched!
如您所见,Zone/digest 在获取数据后没有运行,这就是数据和 UI 没有呈现在页面上的原因。
【问题讨论】:
-
该问题不包含 plunk 或有助于调试问题的内容,这是必须的。 $apply 补丁看起来很可疑。从 $q 和 $http 切换到原生 Promise 和 Fetch 的原因是什么?您有效地消除了 Angular 作为框架的一堆好处,反而产生了一堆问题。看起来不是一个好的权衡。
-
那是因为我无法重现这个。从 $q 和 $http 切换到原生 Promise 和 Fetch 的原因是因为最终目标是用 React 替换 Angular。 ui-router(我们用于路由)现在支持路由到 React 组件。
-
我明白了。一般来说,我建议避免使用隐式摘要,因为它们会导致无法控制的混乱和糟糕的性能。一个合理的中间解决方案是创建一个用 $q 承诺包装
fetch结果的服务(也适合测试)。您还可以检查另一种解决 A1 中原生承诺的方法,stackoverflow.com/questions/39943937/… -
$q 从异步函数内部返回。它不会那样工作。您可以检查返回的承诺仍然是
instanceof Promise。这并不意味着这是您遇到的问题,但这绝对是一个问题。顺便说一句,你永远不应该依赖旧的 Zone,Zone 的全部意义在于它不断修复,因为它是一个巨大的 hack。 -
确实如此,但这不是 async/await 的工作方式。避免这种情况的最简单方法是不要在此处使用
async函数。
标签: javascript angularjs angular-promise fetch-api angularjs-http