2014-11-09 11 views
6

Chcę rejestrować akcje w mojej aplikacji kątowej.Angular JS logowanie danych z obietnicami i przechowywaniem lokalnym

Jeśli nie mogę opublikować posta, chcę dodać artykuł do innego dziennika w magazynie lokalnym, aby przy następnym wysłaniu móc spróbować dodać te elementy.

Po wykonaniu tej czynności chcę spróbować opublikować bieżące elementy. Chcę również mieć przycisk (sync), który przechodzi przez proces bez przechodzenia przez proces dziennika akcji. aby użytkownik mógł spróbować opublikować wszystkie elementy, których wcześniej nie mógł opublikować.

Myślę o zbliżaniu się w ten sposób. na przesłanie

-dodano do lokalnego magazynu, a następnie spróbuj opublikować. (Tak, że pierwsze elementy wcześniejszych stanowisk)

na sukces

-remove artykuł z lokalnej pamięci masowej

w przypadku błędu

-Trzymaj przedmiot do lokalnego przechowywania

Jestem sprawiedliwy sposób w dół ścieżki działania, jak pokazano poniżej, jednak nie jestem pewien, czy jest to najlepszy sposób podejścia do tego.

W tej chwili mogę opublikować dane dotyczące sukcesu, ale nie można usunąć pojedynczego przedmiotu z lokalnego magazynu.

Dodałem w userService nazwie removeName, który skomentowałem w moim poniższym kodzie, ponieważ obecnie usuwa on zmienną _nameLog, a nie lokalny odnośnik do magazynu.

Ale kiedy uruchamiasz kod w codepen demo, publikujesz każdy przedmiot za każdym razem, ponieważ nie usuwam ich z powodzeniem?

Jak mogę usunąć lokalny element pamięci po sukcesie bez usuwania _namelog (ponieważ trzeba pozostać w powtórzeniu ng) lub czy jest inny sposób, w jaki powinienem się do tego zbliżyć?

<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> 
+0

należy pamiętać, że to nie będzie działało w różnych wersjach. protokoły .. http vs. https (chyba że użyjesz jakiegoś rodzaju podkładki iframe) –

+0

Umm, widzę, co próbujesz zrobić, ale nie jestem pewien co jest scenariuszem błędu, o którym mówisz. Dlaczego nie po prostu użyć przechwytywaczy, aby zażądać swoich próśb. W ten sposób będziesz mógł odesłać nieudane żądanie, dotyczące konkretnych scenariuszy, biorąc pod uwagę, z jakim problemem się spotkałeś. – Shouvik

+0

Myślę, że lepszym podejściem byłoby dodanie go w lokalnym sklepie tylko wtedy, gdy błąd ... w ten sposób nie musisz ciągle robić, dodawać/usuwać .. i niektóre funkcje ponownego użycia za pomocą $ interval – harishr

Odpowiedz

2

„Jak mogę usunąć lokalną pozycję magazynowania na sukces bez usuwania się _namelog”

masz kilka problemów z projektu:

1) dla lokalnego storage key = nazwa wartości to tablica. W swoim teście na test nie wiesz, który element tablicy publikujesz. Jeśli wiedziałeś, że możesz pobrać tę tablicę z LS, spnij ten element z tablicy i przypisz go do LS.

2) Wymaga zbyt wiele String do JSON tam iz powrotem.

Stąd moja rada to przestrzeganie schematu nazywania klucza jak nazwa-0, nazwa-1, nazwa-2 i zapisanie każdego wpisu dziennika jako osobnego klucza. Trzymaj licznik w LS. Zwiększ to, dodając wpis do dziennika. Następnie w swoim TestPost można po prostu usunąć ten klucz. Przekaż k jako parametr do testPost z getPosts.

Rozwiązanie jest w 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

Zakładam, że w przypadku korzystania z pamięci lokalnej, aby zapisać nazwy, które nie zostały zsynchronizowane, to dlatego, że chcą, aby upewnić się, że jeśli użytkownik nie synchronizuje przed zamykają przeglądarkę (być może dlatego, że nie mają połączenia internetowego w tym czasie), przy następnym uruchomieniu sesji można spróbować ponownie zsynchronizować te nazwy (mam nadzieję, że gdy mają połączenie z Internetem). Ten rodzaj techniki jest bardzo popularny w aplikacjach mobilnych, ponieważ cały czas przychodzą i wychodzą z Internetu.

W takim przypadku należy pamiętać, że użytkownik może mieć nazwy oczekujące na synchronizację z poprzedniej sesji, a będziesz mieć pewność, że te nazwy będą zsynchronizowane z nowymi nazwami dodanymi z bieżąca sesja.

Najprostszym rozwiązaniem tego scenariusza byłoby założenie, że wszystkie nazwy w pamięci lokalnej są nazwami, które nie zostały zsynchronizowane (ani z bieżącej sesji, ani nawet z poprzedniej sesji).

Gdy użytkownik uruchomi sesję po raz pierwszy, należy odczytać wszystkie nazwy z pamięci lokalnej, aby wstępnie wypełnić tablicę _namelog, aby wyświetlić użytkownikowi wszystkie nazwy, które muszą jeszcze zostać zsynchronizowane.

każdym razem, gdy użytkownik dodaje nazwę, należy zapoznać się z aktualną tablicę nazw Spośród pamięci lokalnej (powiedzmy od klucza namesToPush), wciśnij najnowszy nazwę na tablicy namesToPush jak również _nameLog tablicy, następnie JSON.stringify tablica namesToPush z powrotem do pamięci lokalnej. Chcesz zawsze dodać nazwę do magazynu lokalnego, ponieważ nie wiesz, kiedy użytkownik zamknie bieżącą sesję.

Następnie, gdy użytkownik zsynchronizuje nazwiska, użytkownik będzie czytał wszystkie nazwiska z lokalnego magazynu i publikował je. Jeśli wpis się powiedzie, usuniesz namesToPush z magazynu lokalnego, w przeciwnym razie zostawisz je tam, aby później ponownie zsynchronizować.

Korzyści dla tego podejścia jest to, że

  • Nie musisz starać się śledzić których imiona nie zostały zsynchronizowane w tablicy _nameLog (rozwiązuje obecnego problemu).

  • Korzystanie pojedynczą tablicę w pamięci lokalnej oznacza tylko jedno odczytu/zapisu do pamięci lokalnej o nazwie dodanej i synchronizacji, a tylko jeden kasowania (zapis) na udanej synchronizacji

    • Jeśli użyto wyjątkowy Aby dodać nazwy do pamięci lokalnej, musisz zapisać pierwszy klucz użyty dla niezapisanej partii nazw, aby można było poprawnie pobrać wszystkie niezsynchronizowane nazwy w późniejszej sesji. To może łatwo doprowadzić do off-by-one errors, ponieważ musisz śledzić ten indeks podczas każdej synchronizacji.

    • Mimo że unikalne podejście kluczowe może uchronić Cię przed koniecznością odczytu z pamięci lokalnej po dodaniu nazwy, wszelkie potencjalne oszczędności zostaną utracone po pomyślnej synchronizacji, ponieważ będziesz musiał usunąć wiele nazw z pamięci lokalnej. Może to również prowadzić do problemów, jeśli użytkownik zamknie sesję, zanim wszystkie nazwy zostaną usunięte z lokalnego magazynu.

  • Czytając z pamięci lokalnej każdy post zamiast próbować zachować lokalną tablicę nazw toczących pomaga zapewnić, że nazwa nie zostanie pominięte przez nie będąc w jednej lub drugiej (również pomaga wyeliminować wszelkie możliwości buforowanie problemów lub dwukrotne umieszczanie nazwy z powodu błędu).

+0

wielkie wyjaśnienie! Zobaczę, czy mogę zrealizować twój pomysł. – ak85