【问题标题】:AngularJs - confirm dialog causes the error "$digest already in progress"AngularJs - 确认对话框导致错误“$digest 已经在进行中”
【发布时间】:2016-07-14 22:21:15
【问题描述】:

按照here的回答,我有下面的代码:

.directive('confirmOnExit', function($window) {
    return {
        scope: {},
        link: function(scope) {
            var message = "Changes you made may not be saved.";
            $window.onbeforeunload = function(){
                    return message;
            };
            scope.$on('$locationChangeStart', function(event) {
                if(!$window.confirm("Do you want to leave this page? "+message))
                    event.preventDefault();
            });
            scope.$on('$destroy',function(){
                $window.onbeforeunload = null;
            });
        }
    };
})

在 Chrome 上,一切都很好。但是,在 Firefox 上,几乎每次我点击确认对话框的按钮时,都会出现错误:

Error: [$rootScope:inprog] $digest already in progress

我在网上找到的解决方案大多建议使用$timeout。但是,$timeout 函数中的 event.preventDefault() 似乎并不能阻止 URL 更改。我该怎么办?

【问题讨论】:

  • 你想在这里用scope: {editMode: '<confirmOnExit'},做什么?如果您尝试将指令中的属性与指令本身进行比较,这将导致无限摘要;该指令必须在编译之前进行编译以进行比较....
  • 别费心了。它与问题无关。我从代码中删除了它。谢谢。
  • 不确定是否可以修复。 confirm 暂停 JS 线程,可能会把事情搞砸。我一直在 FF 的 Plunker 上看到 $rootScope:inprog$locationChangeStart listener 是在 within digest 中执行的,所以指令本身应该没有问题,只要它不执行 $apply 或 $digest (它没有)。 $rootScope:inprog 可能是由另一段代码(路由器等)引起的。

标签: javascript angularjs


【解决方案1】:

我刚刚遇到了同样的问题。对我来说,调用confirm 会导致firefox 和IE 出错。为了解决这个问题,如果有要显示的消息,我会立即阻止默认设置,并在超时时运行确认。然后,如果用户单击“离开页面”,我会清除 onbeforeunload 并使用 $location 服务再次设置 url。如果您的应用是单页应用,则在第一个页面加载时会调用 $locationChangeStart,因此您需要在顶部添加一个标志,例如:if (!hasLoaded) { hasLoaded = true; return; }

$rootScope.$on('$locationChangeStart', function (e, newUrl, oldUrl) {
    // Call the function and show the confirm dialogue if necessary
    if ($window.onbeforeunload) {
        let message = $window.onbeforeunload();

        if (message) {
            // Since we're going to show a message, cancel navigation
            e.preventDefault();
            $timeout(() => {
                if (confirm(message)) {
                    // User chose not to stay. Unregister the function so that it doesn't fire again.
                    $window.onbeforeunload = undefined;

                    // Run the url again. We've cleared onbeforeunload, so this won't create a loop
                    $location.url(newUrl.replace($window.location.protocol + '//' + $window.location.host, ''));
                }
            });
        }
    }
})

【讨论】:

    猜你喜欢
    • 2015-07-26
    • 1970-01-01
    • 2013-01-28
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    相关资源
    最近更新 更多