我正在使用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
});