AngularJs - 确认对话框导致错误“$ digest已在进行中”

时间:2016-07-14 22:21:15

标签: javascript angularjs

在回答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。但是,event.preventDefault()函数中的$timeout似乎无法阻止URL更改。我该怎么办?

1 个答案:

答案 0 :(得分:0)

我刚遇到同样的问题。对我来说,调用确认会导致firefox和IE出错。为了解决这个问题,如果有要显示的消息,我会立即阻止默认,并在超时时运行确认。然后,如果用户点击“离开页面”,我清除onbeforeunload并使用$ location服务再次设置网址。如果您的应用是单页应用,则会在首页加载时调用$ 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, ''));
                }
            });
        }
    }
})