Angular 1.4.1 UI Router 10 $digest() วนซ้ำเมื่อ $state.go เรียกใช้ $stateChangeStart

ฉันมีรัฐที่ต้องได้รับอนุญาต ฉันฟังเหตุการณ์ $stateChangeStart และหาก toState.data.protectedและผู้ใช้ไม่ได้รับอนุญาต ฉันจะโทร e.preventDefault() และ $state.go('login')

เมื่อฉันเปิดแอปใน URL รูท ฉันจะถูกเปลี่ยนเส้นทางไปยังสถานะที่ได้รับการป้องกันโดยอัตโนมัติ สิ่งนี้ทำให้เกิด $digest วนซ้ำ 10 $ และสุดท้ายฉันก็อยู่ในสถานะเข้าสู่ระบบเมื่อฉันเปิดแอปใน URL รูท และฉันถูกเปลี่ยนเส้นทางไปยังสถานะที่ได้รับการป้องกันโดยอัตโนมัติ

Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!

ดู plnkr นี้: http://plnkr.co/edit/1voh7m?p=preview

ฉันใช้โค้ดที่คล้ายกันในโครงการอื่นที่มีเชิงมุม 1.2.26 โดยไม่มีข้อผิดพลาดได้สำเร็จ

โค้ดตัวอย่าง angular 1.4.1, ui.router 0.2.15:

//config block
$urlRouterProvider.otherwise('/main');   
$stateProvider
 .state('main', {
   url: '/main',
     templateUrl: 'main.html',
     controller: 'MainController as main',
     data: {'protected': true}
 }) 
 .state('login', {
     url: '/login',
     templateUrl: 'login.html',
     controller: 'LoginController as login'
 });

// in a run block
$rootScope.$on("$stateChangeStart", function (event, toState) {
    if (!event.defaultPrevented && toState.data &&
            toState.data.protected) {
        // the user is not authorized, do not switch to state
        event.preventDefault();
        // go to login page
        $state.go('login');
    }
});

คุณรู้ไหมว่าอะไรทำให้เกิดการวนซ้ำ?

ฉันสงสัยว่าสิ่งต่าง ๆ อาจจะเกิดขึ้นเช่นนี้:

  1. สกัดกั้นการเปลี่ยนไปสู่สถานะ main.submain
  2. เริ่มการเปลี่ยนไปสู่สถานะการเข้าสู่ระบบ
  3. เราเตอร์ UI ได้รับข้อมูลว่าการเปลี่ยนแปลงครั้งแรกถูกยกเลิก
  4. เราเตอร์ UI รัน $urlRouter.update() และเริ่มเปลี่ยนเป็น main.submain

แก้ไข: การกำหนดค่าสถานะที่ง่ายขึ้น


person kvetis    schedule 02.07.2015    source แหล่งที่มา
comment
คุณกำลังกำหนดว่าข้อมูลใดได้รับการคุ้มครองจากที่ใด   -  person user3727843    schedule 02.07.2015
comment
การใช้คำจำกัดความสถานะ: data: {'protected': true} บนสถานะหลัก สถานะได้รับการสืบทอดต้นแบบ ดังนั้นสถานะ main.submain จึงมีค่าเท่ากัน   -  person kvetis    schedule 03.07.2015
comment
ฉันขอโทษที่ฉันแนบเสียงระเบิดที่ไม่ถูกต้องซึ่งไม่ได้แสดงให้เห็นถึงปัญหา   -  person kvetis    schedule 03.07.2015
comment
หากฉันจำไม่ผิด คุณไม่ควรใช้ $urlRouterProvider กับสาขา $urlRouterProvider.otherwise('/main'); หนึ่งสาขา เพราะสำหรับ URL อื่น ๆ ให้ลองเปลี่ยนเส้นทางไปที่ 'main' และคุณอยู่ในวงวนไม่สิ้นสุด ฉันมี เปลี่ยนพลั่วของคุณสักหน่อย ลองตรวจสอบดู: plnkr.co/edit/RyWEusonoBhfQjwD32uu?p=preview   -  person Grundy    schedule 07.07.2015
comment
@กรันดี้ ขอบคุณ ฉันเพิ่งมาที่นี่เพื่อโพสต์คำตอบสำหรับวิธีแก้ปัญหาที่คล้ายกัน ฉันเชื่อว่าคุณควรจะสามารถใช้ $urlRouterProvider.otherwise('/main'); กับโซลูชันของฉันได้ - เพราะคุณเพียงต้องการให้มีการเปลี่ยนเส้นทางเริ่มต้น ฉันชอบเสียงระเบิดของคุณและฉันจะโพสต์คำตอบในอีกสักครู่   -  person kvetis    schedule 07.07.2015


คำตอบ (1)


นี่เป็นปัญหาของ UI.Router – ดูปัญหานี้บน Github: https://github.com/angular-ui/ui-router/issues/600

โดยพื้นฐานแล้ว หากคุณใช้ .otherwise('/main') (ยังชี้ให้เห็นโดย @Grundy) URL จะถูกเปลี่ยนเป็น /main เมื่อไม่สามารถแก้ไขเส้นทางได้ หลังจาก $locationChangeSuccess ผู้ฟังของฉันถูกเรียก และฉันปฏิเสธการเปลี่ยนเส้นทางโดยใช้ event.preventDefault() ซึ่งทำให้ตำแหน่งเปลี่ยนกลับเป็นเส้นทางที่ไม่รู้จัก จึงทำให้ต้องใช้เส้นทางสำรองอีกครั้ง สิ่งนี้ทำให้เกิดการวนรอบไม่สิ้นสุด วิธีแก้ไขคือ:

$urlRouterProvider.otherwise(function($injector) {
  var $state = $injector.get('$state');
  $state.go('main');
});

คุณสามารถระบุฟังก์ชันที่ถูกเรียกด้วย $injector และคุณสามารถเปลี่ยนเส้นทางไปยังสถานะหลักของคุณ (หรือ 404) โดยไม่ต้องเปลี่ยนตำแหน่งกลับไปกลับมา ขอบคุณพวกบน Github ฉันควรจะค้นหาที่นั่นก่อนที่จะโพสต์คำถามนี้

เสียงระเบิดทำงาน: http://plnkr.co/edit/eQXaIk

person kvetis    schedule 07.07.2015
comment
ช่วยได้ขอบคุณมาก! - person Rantiev; 06.06.2017