Helpex - Trao Đổi & Giúp Đỡ - là một trang web tổng hợp, chia sẻ kiến thức và hỏi đáp dành cho các lĩnh vực ở mọi cấp độ và các chuyên gia trong các lĩnh vực liên quan. Chỉ mất một phút để đăng ký.

Tham gia cộng đồng
Ai cũng có thể viết bài và chia sẻ
Ai cũng có thể đặt câu hỏi
Ai cũng có thể trả lời
Các nội dung hay nhất được bình chọn và vươn lên trên đầu
Đã viết
Hoạt động hôm qua
Đã xem 5.3k
4
Trong bài đăng này, chúng ta sẽ xem làm thế nào một ứng dụng Angular 2 có thể được xây dựng xung quanh khái niệm dịch vụ dữ liệu quan sát được. Một ứng dụng có sẵn trong kho lưu trữ này như một ví dụ về cách xây dựng các ứng dụng Angular 2 theo cách này. Bây giờ chúng ta hãy đi qua các chủ đề sau:
  • Kiến trúc thay thế để xây dựng ứng dụng Angular 2
  • Một dịch vụ dữ liệu quan sát được và làm thế nào để sử dụng nó?
  • RxJs Tiêu đề và làm thế nào để sử dụng nó?
  • BehaviourSubject và làm thế nào để sử dụng nó?
  • Làm thế nào để xây dựng một dịch vụ dữ liệu quan sát?
  • Những sai lầm để tránh
  • Kết luận

Kiến trúc thay thế để xây dựng các ứng dụng Angular 2

Có một số khả năng có sẵn để xây dựng các ứng dụng Angular 2. Có xu hướng gần đây để xây dựng các ứng dụng giống như Flux với một nguyên tử trạng thái duy nhất, theo phong cách tương tự Redux. Đây là hai lựa chọn thay thế để xây dựng một ứng dụng theo cách đó:

  • Xây dựng ứng dụng bằng chính Redux, xem bài đăng này để biết thêm chi tiết và một ứng dụng mẫu.
  • Xây dựng ứng dụng bằng cách sử dụng các khái niệm của Redux và nguyên tử trạng thái đơn lẻ, nhưng thực hiện nó trong Rxjs. Xem bài đăng khác này để biết thêm thông tin và một ứng dụng mẫu.

Bài đăng này sẽ trình bày một thay thế không ngụ ý một nguyên tử trạng thái duy nhất và bao gồm sử dụng các dịch vụ dữ liệu quan sát được.

Dịch vụ dữ liệu quan sát được là gì

Dịch vụ dữ liệu quan sát được là dịch vụ tiêm Angular 2 có thể được sử dụng để cung cấp dữ liệu cho nhiều phần của ứng dụng. Dịch vụ, thường được đặt tên là một cửa hàng, có thể được tiêm bất cứ nơi nào cần dữ liệu:

export class App {
    constructor(private todoStore: TodoStore, 
                private uiStateStore: UiStateStore) {
    }
}

Trong trường hợp này, chúng tôi đang tiêm hai cửa hàng, một cửa hàng chứa dữ liệu ứng dụng là danh sách các mã thông báo và một cửa hàng khác chứa trạng thái hiện tại của giao diện người dùng, ví dụ, thông báo lỗi hiện được hiển thị cho người dùng.

Cách sử dụng dịch vụ dữ liệu quan sát được

Dịch vụ dữ liệu cho thấy một quan sát, ví dụ,  TodoStorephơi bày todoscó thể quan sát được. Mỗi giá trị của điều này có thể quan sát được là một danh sách các mã thông báo mới.

Dịch vụ dữ liệu sau đó có thể được sử dụng trực tiếp trong các mẫu bằng cách sử dụng asyncđường ống:

<ul id="todo-list">
    <li *ngFor="#todo of todoStore.todos | async" >
        ...
    </li>
</ul>

Ống này sẽ đăng ký để todoscó thể quan sát và lấy giá trị cuối cùng của nó.

Cách sửa đổi dữ liệu của dịch vụ

Dữ liệu trong các cửa hàng được sửa đổi bằng cách gọi các phương thức hành động trên chúng, ví dụ:

onAddTodo(description) {
    this.todoStore.addTodo(newTodo)
        .subscribe(
            res => {},
            err => {
                this.uiStateStore.endBackendAction();
            }
        );
}

Lưu trữ dữ liệu sau đó sẽ phát ra một giá trị mới cho dữ liệu của nó tùy thuộc vào lệnh gọi phương thức hành động và tất cả các thuê bao sẽ nhận được giá trị mới và cập nhật tương ứng.

Một vài điều thú vị về dịch vụ dữ liệu quan sát được

Lưu ý rằng những người dùng TodoStorekhông biết điều gì đã kích hoạt một danh sách các todos mới được phát ra: thêm công việc, xóa hoặc chuyển đổi công việc. Người tiêu dùng của cửa hàng chỉ biết rằng một giá trị mới có sẵn và chế độ xem sẽ được điều chỉnh phù hợp. Điều này có hiệu quả tách riêng nhiều phần của ứng dụng, vì người tiêu dùng dữ liệu không biết về các công cụ sửa đổi.

Cũng lưu ý rằng các thành phần thông minh của ứng dụng nơi cửa hàng được tiêm không có bất kỳ biến trạng thái nào, đây là một điều tốt vì đây là một nguồn phổ biến của lỗi lập trình.

Cũng cần lưu ý rằng không nơi nào trong các thành phần thông minh là dịch vụ phụ trợ HTTP đang được sử dụng trực tiếp, chỉ các cuộc gọi đến cửa hàng được thực hiện để kích hoạt sửa đổi dữ liệu.

Bây giờ chúng ta đã thấy cách sử dụng một dịch vụ dữ liệu có thể quan sát được, hãy xem cách chúng ta có thể xây dựng một dịch vụ bằng RxJs.

Trung tâm của một dịch vụ dữ liệu quan sát được là Chủ đề RxJs. Các đối tượng thực hiện cả giao diện Người quan sát và Giao diện quan sát, có nghĩa là chúng ta có thể sử dụng chúng để phát ra các giá trị và đăng ký các chỉ số.

Chủ đề không gì khác hơn là một chiếc xe buýt sự kiện truyền thống, nhưng mạnh mẽ hơn nhiều vì nó cung cấp cho tất cả các nhà khai thác chức năng RxJs với nó. Nhưng, tại trung tâm của nó, chúng tôi chỉ cần sử dụng nó để đăng ký giống như bạn thường làm với một quan sát thông thường:

let subject = new Subject();
subject.subscribe(value => console.log('Received new subject value: '))

Nhưng, không giống như một thứ có thể quan sát thông thường, Chủ thể cũng có thể được sử dụng để phát ra các giá trị cho các thuê bao của nó:

Chủ đề có một đặc thù ngăn chúng tôi sử dụng nó để xây dựng các dịch vụ dữ liệu quan sát được: nếu chúng tôi đăng ký nó, chúng tôi sẽ không nhận được giá trị cuối cùng. Thay vào đó, chúng tôi sẽ phải đợi cho đến khi một số phần của ứng dụng gọi next().

Điều này đặt ra một vấn đề đặc biệt là trong các tình huống bootstrapping, trong đó ứng dụng vẫn đang khởi tạo và không phải tất cả người đăng ký đã đăng ký, chẳng hạn, không phải tất cả các asyncống đều có cơ hội tự đăng ký vì không phải tất cả các mẫu đều được khởi tạo.

Giải pháp cho việc này là sử dụng BehaviorSubject. Loại chủ đề này làm gì là nó sẽ trả về khi đăng ký giá trị cuối cùng của luồng hoặc trạng thái ban đầu nếu chưa có giá trị nào được phát ra:

let BehaviourSubject = new BehaviorSubject(initialState);

Có một thuộc tính khác của BehaviorSubject rất thú vị: bất cứ lúc nào chúng ta cũng có thể lấy giá trị hiện tại của luồng:

let currentValue = behaviorSubject.getValue(); 

Điều này làm cho BehaviorSubject là trung tâm của dịch vụ dữ liệu quan sát được, chúng ta không cần nhiều hơn nữa để xây dựng một. Chúng ta hãy xem một ví dụ cụ thể.

Cách xây dựng một dịch vụ dữ liệu quan sát được

Bạn có thể tìm thấy một ví dụ đầy đủ về một cửa hàng ở đây , nhưng đây là phần quan trọng nhất của cửa hàng:

@Injectable()
export class TodoStore {
    _todos: BehaviorSubject> = new BehaviorSubject(List([]));

    constructor(private todoBackendService: TodoBackendService) {
        this.loadInitialData();
    }

    get todos() {
        return asObservable(this._todos);
    }
    ...
}

Chúng ta có thể thấy rằng cửa hàng chứa một biến thành viên duy nhất _todos, đơn giản là một BehaviorSubject với trạng thái ban đầu là một danh sách trống của các todos.

Hàm tạo được tiêm dịch vụ phụ trợ HTTP và đây là nơi duy nhất trong ứng dụng sử dụng dịch vụ này, phần còn lại của ứng dụng đã TodoStoređược chèn thay thế.

Cửa hàng được khởi tạo tại thời điểm xây dựng, vì vậy, một lần nữa, điều quan trọng là chúng tôi sử dụng BehaviorSubject nếu không điều này sẽ không hoạt động.

Nhưng, lý do đằng sau phương pháp getter đó là todos()gì?

Trong ví dụ này, chúng tôi không phơi bày trực tiếp chủ đề cho khách hàng lưu trữ, thay vào đó chúng tôi trả lại một quan sát được.

Điều này là để ngăn khách hàng lưu trữ trực tiếp phát ra giá trị cửa hàng thay vì gọi các phương thức hành động và do đó bỏ qua cửa hàng.

Tránh súp sự kiện

Tiếp xúc trực tiếp với chủ đề có thể dẫn đến các ứng dụng súp sự kiện, trong đó các sự kiện được kết nối với nhau theo một cách khó lý luận. Chúng ta hãy chờ xem điều gì sẽ xảy ra nếu getter không tồn tại.

Truy cập trực tiếp vào một chi tiết triển khai nội bộ như chủ đề giống như trả về các tham chiếu nội bộ cho các cấu trúc dữ liệu nội bộ của một đối tượng; phơi bày nội bộ có nghĩa là mang lại sự kiểm soát của chủ thể và cho phép các bên thứ ba phát ra các giá trị.

Có thể có các trường hợp sử dụng hợp lệ cho việc này, nhưng điều này rất có thể gần như không bao giờ được dự định.

Phần quan trọng của RxJs Beta 2

Trong ứng dụng mẫu, chúng tôi đã sử dụng một asObservable()phương thức tùy chỉnh để chuyển đổi đối tượng thành một thứ có thể quan sát được. Phương pháp tùy chỉnh này sẽ không cần thiết trong các phiên bản RxJ trong tương lai và chúng tôi sẽ có thể thực hiện một cách đơn giản:

subject.asObservable();

Viết một phương pháp hành động

Trong loại ứng dụng này, các hành động chỉ đơn giản là các phương thức được cung cấp bởi các cửa hàng. Ví dụ: hãy xem cách addTodohành động được xây dựng:

addTodo(newTodo:Todo):Observable {
    let obs = this.todoBackendService.saveTodo(newTodo);

    obs.subscribe(
            res => {
                this._todos.next(this._todos.getValue().push(newTodo));
            });

    return obs;
}

Đây chỉ là một cách để làm điều đó. Chúng tôi gọi dịch vụ phụ trợ mà chính nó trả về có thể quan sát được hoặc thành công hoặc có lỗi.

Chúng tôi đăng ký cùng một thứ có thể quan sát được và thành công, chúng tôi tính toán danh sách các todos mới bằng cách thêm các việc cần làm mới vào danh sách hiện tại.

Cạm bẫy # 2 - Tránh các cuộc gọi HTTP trùng lặp

Một điều cần lưu ý trong ví dụ này là lợi nhuận có thể quan sát được bằng HTTP sẽ có hai người đăng ký: một người trong addTodophương thức và người gọi thuê bao addTodo.

Điều này sẽ gây ra một cuộc gọi http trùng lặp do cách thức quan sát hoạt động theo mặc định, bởi vì hai chuỗi xử lý riêng biệt được thiết lập. Xem bài đăng này để biết thêm chi tiết về điều này và các cách khác mà quan sát có thể làm chúng ta ngạc nhiên.

Để khắc phục sự cố này, trong trường hợp này, toán tử chia sẻ đã được gọi trên lớp dịch vụ phụ trợ, để đảm bảo không xảy ra các cuộc gọi HTTP trùng lặp:

saveTodo(newTodo: Todo) : Observable> {
    var headers = new Headers();
    headers.append('Content-Type', 'application/json; charset=utf-8');

    return this.http.post('/todo', JSON.stringify(newTodo.toJS()),{headers}).share();
}

Thông báo share()cuộc gọi cuối cùng. Nếu bất cứ ai có một cách tốt hơn để giải quyết điều này, xin vui lòng cho tôi biết trong các ý kiến. Nhìn qua, tất cả đều hoạt động như thiết kế.

Kết luận

Các dịch vụ hoặc cửa hàng dữ liệu quan sát được là một mô hình đơn giản và trực quan cho phép người ta khai thác sức mạnh của lập trình phản ứng chức năng trong Angular 2 mà không cần đưa ra quá nhiều khái niệm mới.

Các khái niệm quen thuộc như Chủ đề, về cơ bản là một xe buýt sự kiện, là nền tảng của mẫu này, giúp dễ học hơn các mẫu khác cần một số cấu trúc RxJ khác.

Một số biện pháp phòng ngừa như không phơi bày trực tiếp đối tượng có khả năng đủ để cho phép một người giữ ứng dụng đơn giản để tìm ra, nhưng điều này phụ thuộc vào trường hợp sử dụng.

Như chúng ta đã thấy trong các phần cạm bẫy, một số quen thuộc với RxJ và cách thức hoạt động của các vật thể quan sát được yêu cầu. Kiểm tra bài viết trước để biết thêm chi tiết và xem xét ứng dụng mẫu .

Tài liệu tham khảo

Quản lý nhà nước trong các ứng dụng Angular 2 của Victor Savkin ( @victorsavkin )

Quản lý trạng thái trong Angular 2 bằng RxJs của Loïc Marcos Pacheco ( @marcosloic )       

|