ฉันจะจัดเก็บบริบทผู้ใช้ปัจจุบันใน AngularJS ได้อย่างไร?


92

ฉันมี AuthService ซึ่งเข้าสู่ระบบผู้ใช้มันจะส่งคืนวัตถุ json ของผู้ใช้ สิ่งที่ฉันต้องการทำคือตั้งค่าออบเจ็กต์นั้นและให้การเปลี่ยนแปลงทั้งหมดสะท้อนให้เห็นทั่วทั้งแอปพลิเคชัน (สถานะล็อกอิน / ล็อกเอาต์) โดยไม่ต้องรีเฟรชหน้า

ฉันจะทำสิ่งนี้ให้สำเร็จด้วย AngularJS ได้อย่างไร

คำตอบ:


180

วิธีที่ง่ายที่สุดในการดำเนินการนี้คือการใช้บริการ ตัวอย่างเช่น:

app.factory( 'AuthService', function() {
  var currentUser;

  return {
    login: function() { ... },
    logout: function() { ... },
    isLoggedIn: function() { ... },
    currentUser: function() { return currentUser; }
    ...
  };
});

จากนั้นคุณสามารถอ้างอิงสิ่งนี้ในคอนโทรลเลอร์ของคุณ รหัสต่อไปนี้คอยตรวจสอบการเปลี่ยนแปลงของค่าจากบริการ (โดยการเรียกใช้ฟังก์ชันที่ระบุ) จากนั้นจะซิงค์ค่าที่เปลี่ยนแปลงกับขอบเขต

app.controller( 'MainCtrl', function( $scope, AuthService ) {
  $scope.$watch( AuthService.isLoggedIn, function ( isLoggedIn ) {
    $scope.isLoggedIn = isLoggedIn;
    $scope.currentUser = AuthService.currentUser();
  });
});

และแน่นอนคุณสามารถใช้ข้อมูลนั้นได้ตามที่เห็นสมควร เช่นในคำสั่งในเทมเพลต ฯลฯ คุณสามารถทำซ้ำสิ่งนี้ (ปรับแต่งตามสิ่งที่คุณต้องทำ) ในตัวควบคุมเมนูของคุณ ฯลฯ ทั้งหมดนี้จะได้รับการอัปเดตโดยอัตโนมัติเมื่อคุณเปลี่ยนสถานะของบริการ

สิ่งที่เฉพาะเจาะจงขึ้นอยู่กับการใช้งานของคุณ

หวังว่านี่จะช่วยได้!


28
@ChrisNicola จริงๆแล้วใน AngularJS บริการทั้งหมดเป็นแบบ singletons ดังนั้นบริการจึงถูกสร้างขึ้นในครั้งแรกที่มีการร้องขอ (เช่นโดยคอนโทรลเลอร์หรือบริการอื่น) และคำขอที่ตามมาทั้งหมดจะส่งคืนอินสแตนซ์เดียวกันทุกประการ
Josh David Miller

2
อาจเป็นได้ แต่ในฐานะฟังก์ชันเราสามารถลบภายในของวิธีที่เราจัดเก็บข้อมูลนั้นจาก API สาธารณะและไปยัง API ส่วนตัวได้ ทำให้การปรับโครงสร้างใหม่ในภายหลังง่ายขึ้นมาก แต่ฟังก์ชันจะยังคงส่งคืนบูลีน
Josh David Miller

7
นี่อาจเป็นคำถามโง่ ๆ ... แต่จะเกิดอะไรขึ้นหากผู้ใช้รีเฟรชหน้า - ข้อมูลการเข้าสู่ระบบสูญหายหรือไม่?
Tomba

10
@ Tomba นั่นเป็นคำถามที่ดี :-) แน่นอนว่าข้อมูลหายไปเมื่อรีเฟรช โดยปกติคุณจะต้องเก็บข้อมูลเซสชันบางส่วนไว้ในคุกกี้ ข้อมูลเซสชันนั้นสามารถตรวจสอบได้เมื่อตั้งค่าไฟล์AuthService. สิ่งนี้ไม่เพียงช่วยในการรีเฟรชหน้า แต่สำหรับผู้ที่เปิดลิงก์ในแท็บใหม่
Josh David Miller

2
@PixMach คุณถูกต้อง 100% เกี่ยวกับเส้นโค้งการเรียนรู้ คำถามของคุณจะขึ้นอยู่กับหลาย ๆ กรณี แต่นี่คือรูปแบบทั่วไปบางส่วน แยกความกังวล: UI ที่เกี่ยวข้องกับการเริ่มต้นการเข้าสู่ระบบนั้นแยกจากการตรวจสอบสิทธิ์ซึ่งแยกจากสถานะของการตรวจสอบสิทธิ์ซึ่งแยกจากเมนูใด ๆ ที่อาจขึ้นอยู่กับสถานะดังกล่าว การนำทาง / เมนูมักจะได้รับการจัดการอย่างดีที่สุดโดยตัวควบคุมเดียวและสถานะที่ซ้อนกัน (a la ui-router) และการแก้ไขเส้นทางเป็นวิธีที่ดีในการควบคุมการตรวจสอบสิทธิ์ให้แห้ง สิ่งที่คุณเขียนฟังดูถูกต้อง
Josh David Miller

5

ฉันจะแก้ไขการตอบสนองที่ดีของ Josh โดยเพิ่มว่าเนื่องจาก AuthService มักเป็นที่สนใจของทุกคน (พูดว่าใครก็ได้ แต่มุมมองการเข้าสู่ระบบควรหายไปหากไม่มีใครบันทึก) อาจเป็นทางเลือกที่ง่ายกว่าคือการแจ้งให้ผู้สนใจทราบโดยใช้$rootScope.$broadcast('loginStatusChanged', isLoggedIn);(1 ) (2) ในขณะที่บุคคลที่สนใจ (เช่นตัวควบคุม) $scope.$on('loginStatusChanged', function (event, isLoggedIn) { $scope.isLoggedIn = isLoggedIn; }จะฟังโดยใช้

(1) $rootScopeถูกฉีดเป็นข้อโต้แย้งของบริการ

(2) โปรดทราบว่าในกรณีที่เป็นไปได้ของการดำเนินการเข้าสู่ระบบแบบอะซิงโครนัสคุณจะต้องแจ้ง Angular ว่าการออกอากาศจะเปลี่ยนแปลงสิ่งต่างๆโดยรวมไว้ใน$rootScope.$apply()ฟังก์ชัน

ตอนนี้เมื่อพูดถึงการรักษาบริบทของผู้ใช้ในตัวควบคุมทุกตัว / หลายตัวคุณอาจไม่พอใจที่จะฟังการเปลี่ยนแปลงการเข้าสู่ระบบในทุกคนและอาจต้องการฟังเฉพาะในตัวควบคุมการเข้าสู่ระบบที่อยู่บนสุดจากนั้นเพิ่มตัวควบคุมที่รับรู้การเข้าสู่ระบบอื่น ๆ เป็นลูก / ตัวควบคุมแบบฝังของตัวนี้ ด้วยวิธีนี้ตัวควบคุมเด็กจะสามารถดูคุณสมบัติ $ ขอบเขตหลักที่สืบทอดมาเช่นบริบทผู้ใช้ของคุณ


4
ลงคะแนนสำหรับคำอธิบายที่ไม่ถูกต้องเกี่ยวกับฟังก์ชันโรงงาน ความเข้าใจผิดนี้ได้รับการแก้ไขแล้วในความคิดเห็นนี้หลายเดือนก่อนที่คุณจะโพสต์คำตอบของคุณ
Rhys van der Waerden
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.