AngularJS có thể tự động cập nhật dạng xem nếu một mô hình liên tục (cơ sở dữ liệu máy chủ) bị ứng dụng bên ngoài thay đổi không?


81

Tôi chỉ mới bắt đầu làm quen với AngularJS, nhưng tôi muốn xây dựng một ứng dụng web có chế độ xem được tự động cập nhật theo thời gian thực (không làm mới) cho người dùng khi có gì đó thay đổi trong cơ sở dữ liệu phía máy chủ.

AngularJS có thể tự động xử lý điều này (hầu hết) cho tôi không? Và nếu vậy, cơ chế cơ bản tại nơi làm việc là gì?

Ví dụ, bằng cách nào đó bạn có thiết lập AngularJS để thăm dò DB thường xuyên về các thay đổi "mô hình" không? Hoặc sử dụng một số loại cơ chế giống như Comet để thông báo cho mã phía máy khách AngularJS rằng mô hình đã thay đổi?

Trong ứng dụng của tôi, thách thức là phần mềm phía máy chủ (không phải web) khác sẽ cập nhật cơ sở dữ liệu đôi khi. Nhưng câu hỏi này cũng áp dụng cho các ứng dụng web thuần túy, nơi bạn có thể có nhiều máy khách thay đổi cơ sở dữ liệu thông qua các máy khách web AngularJS và mỗi máy khách cần được cập nhật khi một trong số chúng thực hiện thay đổi đối với (mô hình) DB.


Tôi muốn nói thêm rằng tôi đã phát hiện ra rằng Meteor thực hiện tất cả những điều này cho bạn trong khuôn khổ, vì vậy đó là giải pháp ưa thích của tôi lúc này. Có thể kiểm tra lại Angular trong tương lai.
jpeskin

Meteor có thể vẫn còn quá "tươi" - rất tốt để chơi xung quanh, nhưng chưa chứng tỏ được bản thân trong sản xuất lớn (an toàn / khả năng mở rộng / hiệu suất / v.v.). Xác thực đã được thêm vào chỉ hơn một tháng trước. Có vẻ tốt, nhưng sẽ chờ đợi.
Alex Okrushko 13/12/12

@jpeskin Chào bạn. Tôi chỉ biết chính xác bạn đang ở đâu khi bạn hỏi câu hỏi này. Cuối cùng bạn đã làm gì? (Tôi muốn sử dụng Angular). Trân trọng Mark
mark1234

Câu trả lời:


97

Bạn có một vài lựa chọn ...

  1. Bạn có thể thực hiện thăm dò mỗi X mili giây bằng cách sử dụng $timeout$httphoặc nếu dữ liệu bạn đang sử dụng được kết nối với dịch vụ REST, bạn có thể sử dụng $resourcethay thế $http.

  2. Bạn có thể tạo một dịch vụ sử dụng một số triển khai và sử dụng Websocket scope.$applyđể xử lý các thay đổi do socket đẩy. Đây là một ví dụ sử dụng socket.io, một thư viện websocket node.js:

    myApp.factory('Socket', function($rootScope) {
        var socket = io.connect('http://localhost:3000');
    
        //Override socket.on to $apply the changes to angular
        return {
            on: function(eventName, fn) {
                socket.on(eventName, function(data) {
                    $rootScope.$apply(function() {
                        fn(data);
                    });
                });
            },
            emit: socket.emit
        };
    })
    
    function MyCtrl($scope, Socket) {
        Socket.on('content:changed', function(data) {
            $scope.data = data;
        });
        $scope.submitContent = function() {
            socket.emit('content:changed', $scope.data);
        };
    }
    
  3. Bạn có thể nhận được công nghệ thực sự cao và tạo một triển khai websocket đồng bộ mô hình Angular với máy chủ. Khi máy khách thay đổi điều gì đó, thay đổi đó sẽ tự động được gửi đến máy chủ. Hoặc nếu máy chủ thay đổi, nó sẽ được gửi đến máy khách.
    Đây là một ví dụ về điều đó trong phiên bản cũ của Angular, một lần nữa sử dụng socket.io: https://github.com/mhevery/angular-node-socketio

CHỈNH SỬA : Đối với # 3, tôi đã sử dụng Firebase để thực hiện việc này.


Cảm ơn vì đã trả lời cặn kẽ như vậy với một số lựa chọn! Mong muốn được làm cho ý nghĩa của việc này như tôi tìm hiểu thêm về góc :)
jpeskin

4
github.com/mhevery/angular-node-socketio - đã có một sai lầm khi vẽ. cố định nó
Andrew Joslin

Cảm ơn bạn đã trả lời đơn giản để hiểu, rất hữu ích.
mystrdat

Bạn sẽ làm thế nào để tiếp tục hủy liên kết các trình xử lý sự kiện nếu bộ điều khiển cần bị phá hủy?
RushPL

Brian ford có một cách tiếp cận tuyệt vời cho phép bạn xác lập hệ thống sự kiện & dọn dẹp của $ scope. Và làm cho nó thực sự sạch sẽ nói chung. github.com/btford/angular-socket-io . Nhìn vào socket.forward ()
Andrew Joslin

15

Đây là một triển khai sử dụng cầu cảng thay vì nút. Phần anglejs dựa trên ứng dụng angle-seed. Tôi không chắc liệu mã góc có phải là thành ngữ hay không ... nhưng tôi đã kiểm tra rằng điều này hoạt động. HTH -Todd.

TimerWebSocketServlet xem

https://gist.github.com/3047812

controllers.js

// -------------------------------------------------------------
// TimerCtrl
// -------------------------------------------------------------
function TimerCtrl($scope, CurrentTime) {
    $scope.CurrentTime = CurrentTime;
    $scope.CurrentTime.setOnMessageCB(
        function (m) {
            console.log("message invoked in CurrentTimeCB: " + m);
            console.log(m);
            $scope.$apply(function(){
                $scope.currentTime = m.data;
            })
        });
}
TimerCtrl.$inject = ['$scope', 'CurrentTime'];

services.js

angular.module('TimerService', [], function ($provide) {
    $provide.factory('CurrentTime', function () {
        var onOpenCB, onCloseCB, onMessageCB;
        var location = "ws://localhost:8888/api/timer"
        var ws = new WebSocket(location);
        ws.onopen = function () {
            if(onOpenCB !== undefined)
            {
                onOpenCB();
            }
        };
        ws.onclose = function () {
            if(onCloseCB !== undefined)
            {
                onCloseCB();
            }
        };
        ws.onmessage = function (m) {
            console.log(m);
            onMessageCB(m);
        };

        return{
            setOnOpenCB: function(cb){
               onOpenCB = cb;
            },
            setOnCloseCB: function(cb){
                onCloseCB = cb;
            },
            setOnMessageCB: function(cb){
                onMessageCB = cb;
            }
        };
    })});

web.xml

<servlet>
    <servlet-name>TimerServlet</servlet-name>
    <servlet-class>TimerWebSocketServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>TimerServlet</servlet-name>
    <url-pattern>/api/timer/*</url-pattern>
</servlet-mapping>

Đây là một ví dụ sáng giá. Tôi chỉ đang học Angular.js và tự hỏi liệu bạn có ứng dụng hoàn chỉnh với các mẫu, v.v. để học từ đó không?
mac


0

Theo cuốn sách "Discover Meteor", đồng hồ / phạm vi Angular tương tự như các tính toán của Meteor về khả năng phản ứng ... nhưng Angular chỉ dành cho máy khách và cung cấp khả năng kiểm soát ít chi tiết hơn Meteor.

Ấn tượng của tôi là sử dụng Angular có thể phù hợp hơn để thêm phản ứng vào một ứng dụng hiện có, trong khi Meteor tăng vọt khi bạn sử dụng nó cho toàn bộ ứng dụng. Nhưng tôi chưa có kinh nghiệm thực sự với Angular (mặc dù tôi đã xây dựng một số ứng dụng Meteor nhỏ).


0

Vì vậy, Andy Joslin đã đề cập đến giải pháp tốt nhất trong sự đồng ý của tôi trong câu trả lời của anh ấy, tùy chọn thứ 3, đó là duy trì trạng thái hai chiều thông qua websockets hoặc bất kỳ thư viện không đồng bộ nào khác mà bạn đang xử lý (đây sẽ là API thông báo Chrome cho Tiện ích mở rộng của Chrome và Ví dụ: ứng dụng) và toddg đã đưa ra một ví dụ về cách đạt được điều đó. Tuy nhiên, trong ví dụ của mình, anh ấy đang triển khai một anti-pattern trong AngularJS: dịch vụ đang gọi bộ điều khiển. Thay vào đó, mô hình nên được đặt bên trong dịch vụ và sau đó được tham chiếu từ bộ điều khiển.

Các lệnh gọi lại của ổ cắm dịch vụ sẽ sửa đổi mô hình dịch vụ và bởi vì nó được tham chiếu từ bộ điều khiển, nó sẽ cập nhật chế độ xem. Hãy cẩn thận nếu bạn đang xử lý các kiểu dữ liệu nguyên thủy hoặc các biến có thể được gán lại, những biến đó sẽ cần một chiếc đồng hồ trên bộ điều khiển để thực hiện việc này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.