2014-11-09 21 views
6

Tôi muốn ghi lại các hành động trong ứng dụng góc của mình.Dữ liệu nhật ký JS góc với lời hứa và lưu trữ cục bộ

Nếu tôi không thể đăng bài thì tôi muốn thêm mục vào nhật ký khác trong bộ nhớ cục bộ để lần sau tôi đăng, tôi cũng có thể thử và thêm các mục này.

Sau khi thực hiện xong, tôi muốn thử và đăng các mục hiện tại. Tôi cũng muốn có một nút (đồng bộ) chạy qua quá trình mà không phải trải qua quá trình đăng nhập hành động. để người dùng có thể thử và đăng tất cả các mục họ chưa thể đăng trước đó.

Tôi đang nghĩ đến việc tiếp cận nó như thế này. khi gửi

-thêm mục vào bộ nhớ cục bộ, sau đó thử đăng. (Để nó đăng tải các mặt hàng trước đó đầu tiên)

trên thành công

mục -Xoá từ local storage

về lỗi

mục -keep để lưu trữ địa phương

tôi một cách công bằng xuống theo dõi của việc này làm việc như hình dưới đây, tuy nhiên tôi không chắc chắn về việc liệu đây là cách tốt nhất để tiếp cận này.

Hiện tại tôi có thể đăng dữ liệu thành công nhưng không xóa mục riêng lẻ khỏi bộ nhớ cục bộ.

Tôi đã thêm vào một userService gọi là removeName mà tôi đã nhận xét trong mã dưới đây của tôi, vì nó hiện đang xóa _nameLog thay vì tham chiếu bộ nhớ cục bộ cho mục đó.

Nhưng khi bạn chạy mã trong codepen demo, nó sẽ đăng mỗi mục mỗi khi tôi không xóa chúng thành công?

Làm cách nào để loại bỏ mục lưu trữ cục bộ thành công mà không xóa _namelog (vì điều này cần phải nằm trong ng-lặp lại) hoặc có cách nào khác để tiếp cận điều này không?

<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

hãy nhớ điều này sẽ không hoạt động trên khác biệt. protocals .. http so với https (trừ khi tất nhiên, bạn sử dụng một số loại shim iframe) –

+0

Umm, tôi thấy những gì bạn đang cố gắng làm, nhưng tôi không chắc chắn kịch bản lỗi bạn đang nói đến là gì. Tại sao không chỉ sử dụng interceptor để requeue bạn yêu cầu. Bằng cách này, bạn sẽ có thể đăng lại yêu cầu không thành công, đối với các tình huống cụ thể bằng cách tính đến vấn đề bạn gặp phải. – Shouvik

+0

tôi nghĩ rằng cách tiếp cận tốt hơn sẽ là thêm nó vào cửa hàng địa phương chỉ khi lỗi ... theo cách đó bạn không cần phải tiếp tục thêm/xóa .. và chức năng thử lại bằng cách sử dụng $ interval – harishr

Trả lời

2

"Làm thế nào tôi có thể loại bỏ các mục lưu trữ cục bộ trên thành công mà không cần tháo các _namelog"

Bạn có một vài vấn đề với thiết kế của bạn:

1) Đối với các địa phương khóa lưu trữ = tên giá trị là một mảng. Trong testPost của bạn, bạn không biết mục nào bạn đang đăng. Nếu bạn biết bạn có thể lấy mảng đó từ LS ghép phần tử đó từ mảng và xâu chuỗi lại thành LS.

2) Yêu cầu quá nhiều Chuỗi thành JSON qua lại.

Do đó lời khuyên của tôi là tuân theo lược đồ đặt tên khóa như name-0, name-1, name-2 và lưu trữ mỗi mục nhập nhật ký dưới dạng khóa riêng biệt. Giữ một bộ đếm trong LS. Gia tăng điều này khi bạn thêm mục nhập nhật ký. Sau đó, trong testPost của bạn, bạn chỉ có thể xóa khóa đó. Vượt qua k làm tham số cho testPost từ getPost.

Giải pháp là trong 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

tôi giả sử rằng nếu bạn đang sử dụng lưu trữ cục bộ để lưu tên chưa được đồng bộ hóa, đó là vì bạn muốn chắc chắn rằng nếu người dùng không đồng bộ trước họ đóng trình duyệt của họ (có thể bởi vì họ không có kết nối internet vào thời điểm đó), lần sau khi họ bắt đầu phiên, bạn có thể thử đồng bộ hóa lại các tên đó (hy vọng khi họ có kết nối internet). Kiểu kỹ thuật này rất phổ biến với các ứng dụng dành cho thiết bị di động khi họ vào và ra khỏi kết nối internet mọi lúc.

Nếu trường hợp này xảy ra, bạn cần lưu ý rằng người dùng có thể có tên chờ để đồng bộ hóa từ phiên trước và bạn sẽ muốn đảm bảo rằng những tên đó được đồng bộ hóa với bất kỳ tên mới nào được thêm từ phiên hiện tại.

Giải pháp dễ nhất cho trường hợp này là giả định rằng tất cả các tên trong bộ nhớ cục bộ là các tên chưa được đồng bộ hóa (hoặc từ phiên hiện tại hoặc thậm chí phiên trước đó).

Khi người dùng bắt đầu phiên, bạn sẽ đọc tất cả các tên ra khỏi bộ nhớ cục bộ để điền trước mảng _namelog để hiển thị cho người dùng tất cả các tên vẫn cần được đồng bộ hóa.

Mỗi khi người dùng thêm một tên, bạn sẽ đọc những mảng hiện tại của tên ra khỏi lưu trữ cục bộ (giả sử từ khóa namesToPush), đẩy tên mới nhất đến các mảng namesToPush cũng như _nameLog mảng, sau đó JSON.stringify mảng namesToPush trở lại bộ nhớ cục bộ. Bạn muốn luôn thêm tên vào bộ nhớ cục bộ vì bạn không biết khi nào người dùng sẽ đóng phiên hiện tại.

Sau đó, khi người dùng đồng bộ hóa tên, bạn sẽ đọc tất cả tên từ bộ nhớ cục bộ và đăng chúng. Nếu bài đăng thành công, bạn xóa namesToPush khỏi bộ nhớ cục bộ, nếu không bạn sẽ để chúng ở đó để được đồng bộ hóa lại sau.

Các lợi ích cho phương pháp này là rằng

  • Bạn không cần phải cố gắng để theo dõi trong đó tên chưa được đồng bộ hóa trong mảng _nameLog (giải quyết vấn đề hiện tại).

  • Sử dụng một mảng duy nhất trong lưu trữ địa phương có nghĩa là chỉ có một đọc/ghi vào bộ nhớ cục bộ trên tên bổ sung và đồng bộ, và chỉ có một xóa (ghi) trên một đồng bộ thành công

    • Nếu bạn sử dụng một độc đáo để thêm tên vào bộ nhớ cục bộ, bạn sẽ phải lưu khóa đầu tiên được sử dụng cho một loạt các tên chưa được lưu để bạn có thể lấy đúng tất cả các tên chưa được đồng bộ hóa trong một phiên sau. Điều này có thể dễ dàng dẫn đến off-by-one errors vì bạn phải theo dõi chỉ mục này mọi đồng bộ hóa.

    • Mặc dù cách tiếp cận khóa duy nhất có thể giúp bạn không phải đọc từ bộ nhớ cục bộ khi thêm tên, mọi khoản tiết kiệm tiềm năng sẽ bị mất khi đồng bộ hóa thành công vì bạn sẽ phải xóa nhiều tên đó khỏi bộ nhớ cục bộ. Điều này cũng có thể dẫn đến sự cố nếu người dùng đóng phiên trước khi tất cả các tên bị xóa khỏi bộ nhớ cục bộ.

  • Bằng cách đọc từ lưu trữ địa phương mỗi bài thay vì cố gắng giữ một mảng địa phương tên cấp phát giúp đảm bảo rằng không có tên được bỏ qua bởi không phải là trong một hay khác (nó cũng giúp loại bỏ bất kỳ tiềm năng vấn đề bộ nhớ đệm hoặc đăng tên hai lần do lỗi).

+0

giải thích tuyệt vời! Tôi sẽ xem nếu tôi có thể thực hiện ý tưởng của bạn. – ak85

Các vấn đề liên quan