写点什么

一个 ExpressionChangedAfterItHasBeenCheckedError 错误的解决过程

作者:Jerry Wang
  • 2022 年 10 月 07 日
    四川
  • 本文字数:1025 字

    阅读完需:约 3 分钟

一个 ExpressionChangedAfterItHasBeenCheckedError 错误的解决过程

问题描述

我的 Component 里有一个 selectedPane 字段(第 56 行),作为数据源显示在 div 标签里(代码第 47 行):



代码第 51 行,我使用 @ViewChild 这个 query,将第 45 行的 div 元素,查询出来并通过 52 行的 set 函数,赋给 this.selectedPane.


运行时收到这条错误消息:


ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: ''. Current value: 'undefined'.


问题分析

从调试器里能看出,旧的 value 是 "", 新的 value 是 undefined,因此抛出异常:



if (ngDevMode && isInCheckNoChangesMode()) {            // View engine didn't report undefined values as changed on the first checkNoChanges pass            // (before the change detection was run).            const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;            if (!devModeEqual(oldValueToCompare, value)) {                const details = getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value);                throwErrorIfNoChangesMode(oldValue === NO_CHANGE, details.oldValue, details.newValue, details.propName);            }            // There was a change, but the `devModeEqual` decided that the change is exempt from an error.            // For this reason we exit as if no change. The early exit is needed to prevent the changed            // value to be written into `LView` (If we would write the new value that we would not see it            // as change on next CD.)            return false;        }
复制代码


这个错误在 Angular 官网的这个视频里有详细的解释:


如果在 Angular 框架执行完变更检测之后,再修改属性值,比如在 ngAfterViewInit 或者本文例子的 set 函数里,就会抛出这个异常。


解决方案

一种 StackOverflow 上经常提到的解决方案就是,使用异步更新, 将值的修改推迟到下一次变更检测周期中执行:



使用 setTimeout 配合延迟为 0 的调用方式,使得这个更新对应的检测,发生在下一次浏览器的宏任务队列中。



采用立即执行的 Promise 可以达到同样的效果:


Promise.resolve().then(() => this.loading false);
复制代码




错误消失了:



另一种解决方案是,在 set 函数里修改了属性值之后,立即手动触发一次 change detection:



能实现同样的效果:



发布于: 刚刚阅读数: 3
用户头像

Jerry Wang

关注

🏆InfoQ写作平台-签约作者🏆 2017.12.03 加入

SAP成都研究院开发专家,SAP社区导师,SAP中国技术大使。2007 年从电子科技大学计算机专业硕士毕业后加入 SAP 成都研究院工作至今。工作中使用 ABAP, Java, JavaScript 和 TypeScript 进行开发。

评论

发布
暂无评论
一个 ExpressionChangedAfterItHasBeenCheckedError 错误的解决过程_typescript_Jerry Wang_InfoQ写作社区