Angular JS logging data with promises and local storage

I want to register actions in my angular application.

If I cannot send the message, I want to add the item to another local storage log so that the next time I send the message, I can try and add these items.

Once this is done, I want to try to post the current items. I also want to have a (sync) button that goes through the process without going through the action log process. so that the user can try to publish all the elements that they could not publish before.

I’m thinking of approaching him like that. on submit

-add to local storage, then try sending a message. (so that it first places the previous items)

of success

-change item from local storage

on error

-support item in local storage

I am a glorious way down the road to getting this job, as shown below, however I'm not sure if this is the best way to get close to this.

At the moment, I can publish success data, but not delete a single item from local storage.

I added the removeName name to userService, which I commented out in my lower code, as it currently removes _nameLog, and not a link to the local repository file.

But when you run the code in the codepen demo , does it publish every element every time, since I do not delete them on successful completion?

How can I delete the local repository item on successful execution without deleting _namelog (since this is necessary to continue in ng-repeat), or is there another way I should get close to this?

<body ng-app="myApp"> <div ng-controller="MyCtrl"> <input type="text" ng-model="updatedname"> <input type="button" value="Change name" ng-click="changeName(updatedname)"/> <br/> Hello, {{name}}! <ul> <li ng-repeat="name in nameLog">{{name.value}} - {{name.time}}</li> </ul> <input type="button" value="sync" ng-click="syncPosts()"/> </div> </body> <script> var myApp = angular.module('myApp',[]); myApp.factory('UserService', ['$window','$http', function($window,$http) { var _nameLog = []; var userService = {}; userService.name = "John"; userService.ChangeName = function (value) { userService.name = value; }; userService.logName = function (value) { _nameLog.push ({ "value":value, "time" :Date.now() }); }; userService.removeName = function (value) { return delete _nameLog[0]; }; userService.getNameLog = function(){ return _nameLog; }; userService.setLS = function(key, value) { $window.localStorage[key] = value; }, userService.getLS = function(key, defaultValue) { return $window.localStorage[key] || defaultValue; }; userService.setObject = function(key, value) { $window.localStorage[key] = JSON.stringify(value); }; userService.getObject = function(key) { return JSON.parse($window.localStorage[key] || '{}'); }; userService.testPost = function(myVal,myTime) { return $http.post('http://jsonplaceholder.typicode.com/posts', {title:myVal,body:myTime,userId: 1}); }; return userService; }]); function MyCtrl($scope, UserService) { $scope.name = UserService.name; $scope.updatedname=""; $scope.changeName=function(data){ $scope.updateServiceName(data); } $scope.updateServiceName = function(name){ UserService.ChangeName(name); UserService.logName(name); $scope.name = UserService.name; $scope.nameLog = UserService.getNameLog(); UserService.setLS('name', JSON.stringify($scope.nameLog)); getPosts(); } $scope.syncPosts = function(){ getPosts(); } function testPost(myVal,myTime) { UserService.testPost(myVal,myTime) .success(function(data, status, headers, config) { console.log('success'); console.log(data); //UserService.removeName(); }) .error(function(data, status, headers, config) { console.log('error'); }); } function getPosts(){ getObj = UserService.getObject('name'); for (var k in getObj) { var myVal = getObj[k].value; var myTime = getObj[k].time; testPost(myVal,myTime); console.log(getObj[k].value); } } } </script> 
+6
source share
2 answers

"How to remove a local storage item on success without deleting _namelog"

You have a few problems with your design:

1) For the local storage key = name, the value is an array. In your testPost, you don't know which element of the array you are posting. If you knew you could extract this array from LS, connect this element to the array and return it to LS.

2) It takes too many lines for JSON back and forth.

So my advice is to follow a key naming scheme such as name-0, name-1, name-2, and store each log entry as a separate key. Keep the counter in LS. Increase this when adding a journal entry. Then in your testPost you can simply delete this key. Pass k as the testPost parameter from getPosts.

The solution is in the plunkr solution.

  <body ng-app="myApp"> <div ng-controller="MyCtrl as ctrl"> <input type="text" ng-model="updatedname"> <input type="button" value="Change name" ng-click="changeName(updatedname)"/> <br/> Hello, {{name}}! <ul> <li ng-repeat="name in nameLog">{{name.value}} - {{name.time}}</li> </ul> <input type="button" value="sync" ng-click="syncPosts()"/> </div> </body> angular.module('myApp', []) .factory('UserService', ['$window', '$http', function($window, $http) { var _nameLog = []; var userService = {}; userService.name = "John"; userService.ChangeName = function(value) { userService.name = value; }; userService.logName = function(value) { var logCount = userService.getLS('count', undefined); if (angular.isUndefined(logCount)) { logCount = -1;//so that this gets incremented to 0 } var obj = { "value": value, "time": Date.now() }; logCount++; _nameLog.push(obj); this.setObject('count',logCount); this.setObject('name#'+logCount, obj); }; userService.removeName = function(value) { return delete _nameLog[0]; }; userService.getNameLog = function() { return _nameLog; }; userService.setLS = function(key, value) { $window.localStorage[key] = value; }, userService.getLS = function(key, defaultValue) { return $window.localStorage[key] || defaultValue; }; userService.deleteLS = function(key) { return $window.localStorage.removeItem(key); }; userService.setObject = function(key, value) { $window.localStorage[key] = JSON.stringify(value); }; userService.getObject = function(key) { return JSON.parse($window.localStorage[key] || '{}'); }; userService.testPost = function(myVal, myTime) { return $http.post('http://jsonplaceholder.typicode.com/posts', { title: myVal, body: myTime, userId: 1 }); }; return userService; } ]) .controller('MyCtrl', ['$scope', 'UserService', function($scope, UserService) { $scope.name = UserService.name; $scope.updatedname = ""; $scope.changeName = function(data) { $scope.updateServiceName(data); } $scope.updateServiceName = function(name) { UserService.ChangeName(name); UserService.logName(name); $scope.name = UserService.name; $scope.nameLog = UserService.getNameLog(); //$scope.getPosts(); } $scope.syncPosts = function() { $scope.getPosts(); } $scope.testPost = function(myVal, myTime, k) { UserService.testPost(myVal, myTime) .success(function(data, status, headers, config) { console.log('success'); console.log(data); //UserService.removeName(); UserService.deleteLS('name#'+k); }) .error(function(data, status, headers, config) { console.log('error'); }); } $scope.getPosts = function() { var logCount = UserService.getLS('count', undefined); if (angular.isUndefined(logCount)) { return;//there is nothing in log } for(var k = 0 ; k <= logCount ; k++) { var getObj = UserService.getObject('name#'+k); var myVal = getObj.value; var myTime = getObj.time; $scope.testPost(myVal, myTime, k); console.log(getObj.value); } } } ]); 
+2
source

I assume that if you use local storage to save names that were not synchronized, this is because you want to make sure that if the user does not synchronize before closing their browser (possibly because they do not have an Internet connection in at that time), the next time you start the session, you can try to re-synchronize these names (I hope when they have an Internet connection). This type of technology is very popular among mobile applications, as they constantly appear and exit the Internet connection.

If so, it is important to remember that the user may have names that are waiting for synchronization from a previous session, and you want to make sure that these names are synchronized with any new names added from the current session.

The simplest solution for this scenario would be to assume that all the names in the local storage are names that were not synchronized (either from the current session, or even from the previous session).

When the user starts the session first, you must read all the names from the local storage to pre-populate the _namelog array to show the user all the names that still need to be synchronized.

Each time the user adds a name, you must read the current array of names from the local storage (say, from the namesToPush key), click the new name into the namesToPush array, as well as the _namelog array, then the JSON.stringify array back to the local storage. You want to always add the name to the local storage, since you do not know when the user will close the current session.

Then, when the user synchronizes the names, you should read all the names from the local storage and publish them. If the message is successful, you delete namesToPush from the local storage, otherwise you will leave them there for later synchronization.

The advantages of this approach are that

  • You do not need to try to keep track of which names were not synchronized in the _namelog array (solves the current problem).

  • Using one array in local storage means only one read / write to the local memory when adding a name and synchronization, and only one deletion (writing) for successful synchronization

    • If you used a unique key to add names to the local storage, you will need to save the first key used for the unsaved batch of names so that you can correctly get all the names that are not yet synchronized in a later session. This can easily lead to incremental errors , since you need to keep track of this index every time you synchronize.

    • Although a unique key approach can save you the trouble of reading from the local storage when adding a name, any potential savings are lost if synchronization is successful, since you will have to delete many names from the local storage. It can also lead to problems if the user closes the session before all names are deleted from the local storage.

  • When reading from local storage, each post, instead of trying to save a local array of pending names, helps to ensure that the name will not be skipped if it is not in one or the other (this also helps eliminate any potential cache problems or publish the name twice from for mistakes).

+2
source

Source: https://habr.com/ru/post/977933/


All Articles