Angular - 在http请求之后模型更改后不更新视图

时间:2017-10-18 07:51:09

标签: angularjs ionic-framework data-binding angular-digest

我正在使用Angular 1.5,Ionic 1.3和Cordova编写应用程序。现在我正在开发用户将按下按钮的部分,应用程序将时间和地理位置存储在localStorage中,然后将数据发布回服务器并更新视图。我遇到的问题是,在一种情况下,视图在模型更改后没有更新。

我尝试了一些事情:$ timeout,$ rootScope,$ q似乎没有解决问题。它只发生在iOS而不是Android上。我也在使用这个库来帮助处理地理定位过程:https://github.com/dpa99c/cordova-diagnostic-plugin

我知道第三方库问题,它可能不是Angular摘要周期的一部分,但我用$ q包装它并且没有运气:https://www.searchenginepeople.com/blog/top-5-technical-issues-large-sites-angularjs.html

我在这里发布伪代码。

view.html

<ion-view cache-view="false">
<ion-content>
            <span>{{ data.text }}</span>
            <span>{{ data.date }}</span>
            <span>{{ data.isSync }}</span>
            <button ng-click="showPopup()">Click</button>
</ion-content>
</ion-view>

controller.js

(function () {
    'use strict';

    angular
        .module('myApp')
        .controller('ViewController', ViewController);

    ViewController.$inject = ['$scope', 'GeoDataModelService'];

    function ViewController($scope, GeoDataModelService) {
        $scope.data = GeoDataModelService.value;
        $scope.showPopup = GeoDataModelService.showPopup();
    }

})();

service.js

(function () {
    'use strict';

    angular
        .module('myApp')
        .factory('GeoDataModelService', GeoDataModelService);

    GeoDataModelService.$inject = [
        ...
    ];

    function GeoDataModelService(
        ...
        ) {

        //data model
        var dataModel = {
            isSync: true,
            text: null,
            date: null
        };

        return {
            value: dataModel,
            showPopup: showPopup
        };

        function showPopup() { //gets called
            $ionicPopup.confirm({
                title: 'clock now ?',
                buttons: [{
                    text: 'CONTINUE',
                    type: 'button-positive',
                    onTap: function () {
                        geoData();
                    }
                }, {
                    text: 'CANCEL',
                    type: 'button-default'
                }]
            });
        };

        function geoData() {
            getLocationServicesStatus()
                .then(geoServiceSuccessful)
                .catch(function(err) {});
        };

        function geoServiceSuccessful() { //gets called
            DataModelService.createRecord();
            sendDataToServerAfterGeoData();
        }

        function getLocationServicesStatus() {
            console.log(' getLocationServicesStatus');

            var deferred = $q.defer();

            //this is outside of angular
            cordova.plugins.diagnostic.isLocationAvailable(
                function (available) {
                    if (available) {
                        deferred.resolve(true);
                    } else {
                        deferred.reject(false);
                    }
                }, function (error) {
                    deferred.reject(false);
                }
            );

            return deferred.promise;
        }

        function updateDataModel(source) {
            console.log('source ', source); //this one is not null
            if (source != null) {
                dataModel.text = source.text;
                dataModel.date = source.date;
                console.log(JSON.stringify(dataModel)); //correct
            }
        }

        function sendDataToServerAfterGeoData() {

            //if offline just skip the server post 
            if (!navigator.onLine) {

                // trigger digest cycle
                $timeout(function () {
                    updateModelAfterRecord(); //this one works fine
                }, 0);

                return;
            }

            var clockins = DataModelService.load(); //load from local storage

            console.log(' * * * * * HERE WE GO * * * * * ');

            //this service returns an http promise
            DataModelService
                .sendLocalDataToService(clockins)
                .then(sendDataToServerAfterGeoDataSuccess)
                .then(getClockDataToServerAfterGeoSuccess)
                .catch(handleSendDeviceDataToServerFail);
        };

        function sendDataToServerAfterGeoDataSuccess() {
            console.log(' sendDataToServerAfterGeoDataSuccess ');
            //this service returns an http promise
            return DataModelService.getDataModelFromServer();
        }

        function getClockDataToServerAfterGeoSuccess(response) {
            console.log(' getClockDataToServerAfterGeoSuccess ', response);
            console.log('1 dataModel: ', dataModel);

            // $timeout not working here
            // $rootScope.asyncEval not working either
            // $rootScope.$apply threw an error

            console.log(' 2 dataModel: ', dataModel); //correct
            dataModel.isSync = true;
            updateDataModel(response); //goes through this code
            console.log('3 dataModel: ', dataModel); //correct
            console.log(' 4 dataModel: ', dataModel); //correct
            console.log('5 dataModel: ', dataModel); //correct

            return response; //tried to leave this out - no effect
        }

        function handleSendDeviceDataToServerFail(error) {
            console.log('handleSendDeviceDataToServerFail ', error);
            var clockins = DataModelService.load();
            dataModel.isSync = false;
            updateDataModel(clockins); //this works
        }

        function updateModelAfterRecord() {
            dataModel.isSync = false;
            var data = DataModelService.load();
            updateDataModel(data);
        }


    }

})();

我添加了一个观察者,看看数据是否在变化:

$scope.$watch('data.text', function(newVal, oldVal) {
  console.log(' new val', newVal); //this is correct
});

0 个答案:

没有答案