2016-03-27 14 views
0

Meine App verfügt über ein Ereigniskonzept mit Breiten- und Längenattributen. Clientseitig möchte ich navigator.geolocation verwenden, um die aktuelle Entfernung zu jedem Ereignis zu berechnen und es in der Ansicht anzuzeigen.Erstellen einer asynchronen Instanzmethode für das ngResource-Objekt

Unten ist was ich bisher habe. Es läuft, aber es steckt in einer Endlosschleife (Fehler weiter unten).

factory('ys$currentPosition', ['$q', '$window', function($q, $window){ 
    'use strict'; 
    return { 
    position: function(){ 
     var deferred = $q.defer(); 
     if ($window.navigator.geolocation) { 
     $window.navigator.geolocation.getCurrentPosition(
      function (position) { 
      deferred.resolve(position); 
      }, 
      function (err) { 
      deferred.reject(err); 
      } 
     ); 
     } else { 
     deferred.reject('Geolocation not supported.'); 
     } 
     return deferred.promise; 
    } 
    }; 
}]). 

factory('Event', ['$resource', 'ys$currentPosition', function($resource, ys$currentPosition){ 
    'use strict'; 
    var Event = $resource($server_hostname + '/api/v4/organizations/' + $org_id + '/events/:id', {}, {}); 

    Event.prototype.distance = function(){ 
    var this_event = this; 
    return ys$currentPosition.position().then(function(position){ 
     return getDistanceFromLatLonInMi(
     position.coords.latitude, 
     position.coords.longitude, 
     this_event.latitude, 
     this_event.longitude 
    ) 
    }); 
    } 
    return Event; 
}]). 

View (in HAML): 
%ys-index-row-right{"ng-if" => "item.distance()"} 
    %i.fa.fa-map-marker 
    %span 
    {{ item.distance() }} mi 

ist hier, dass Fehler:

angular-0195028….js?body=1:69 Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting! 
Watchers fired in the last 5 iterations: [[{"msg":"item.distance()","newVal":{},"oldVal":{}}],[{"msg":"item.distance()","newVal":{},"oldVal":"..."}],[{"msg":"item.distance()","newVal":{},"oldVal":"..."}],[{"msg":"item.distance()","newVal":{},"oldVal":"..."}],[{"msg":"item.distance()","newVal":{},"oldVal":"..."}]] 

Plunker:

https://plnkr.co/edit/zk5ETxCzvzKYAJOlUPPA?p=preview

+0

Seine ständig wechselnden .. – amanuel2

+0

Erstellen Sie einen Plunder –

+0

@DrJones Plunker hinzugefügt - danke! – jsharpe

Antwort

0

I ‚fixed‘ dies durch die Anerkennung, dass Sie nicht der Ansicht, die das Versprechen auszupacken erwarten können. Also, innerhalb des Controllers nur über $ scope.events iteriert und eine Methode aufgerufen, die 1) die Versprechen ausgepackt 2) den Abstand Wert auf das Objekt direkt einstellen.

0

So sah ich die Endlosschleife Fehler, wenn ich "Block" gewählt, wenn der Browser für die Geolokalisierung gefragt. Wenn ich "Zulassen" gesagt habe, hat es funktioniert. Nachdem ich gesagt habe, dass der Code einigermaßen aufgeräumt und in einzelne Einheiten aufgeteilt werden könnte, um den Fehler leichter aufzuspüren und die App lesbarer zu machen. Beigefügt ist der Ansatz, den ich genommen haben kann: Plunker Here

nur script.js Code hier

var app = angular.module('app', ['ngMockE2E', 'ngResource', 'controllers']); 

app.run(function($httpBackend) { 
    events = [{title: 'hello world', latitude: '38', longitude: '-77'}]; 
    $httpBackend.whenGET('/foos').respond(events); 
}); 

app.factory('ys$currentPosition', ['$q', '$window', function($q, $window){ 
    'use strict'; 
    return { 
    position: function(){ 
     var deferred = $q.defer(); 
     if ($window.navigator.geolocation) { 
     $window.navigator.geolocation.getCurrentPosition(
      function (position) { 
      deferred.resolve(position); 
      }, 
      function (err) { 
      deferred.reject(err); 
      } 
     ); 
     } else { 
     deferred.reject('Geolocation not supported.'); 
     } 
     return deferred.promise; 
    } 
    }; 
}]). 

factory('EventService', function($q, $http, ys$currentPosition) { 
    'use strict'; 

    function fetchEvents() { 
    var deferred = $q.defer(); 
    $http.get('/foos').then(function(result){ 
     deferred.resolve(result.data); 
    }); 
    return deferred.promise; 
    } 

    function appendDistanceFromEvents(events) { 
    var deferred = $q.defer(); 
    ys$currentPosition.position().then(function(position){ 
     _.forEach(events, function(event) { 
     event.distance = determineDistanceFromEvent(event, position); 
     }); 
     deferred.resolve(events); 
    }); 
    return deferred.promise; 
    } 

    function determineDistanceFromEvent(event, userPosition) { 
    var dist = getDistanceFromLatLonInMi(
     userPosition.coords.latitude, 
     userPosition.coords.longitude, 
     event.latitude, 
     event.longitude 
    ) 
     console.log(dist) 
     return dist; 
    } 

    var deg2rad = function(deg) { 
    return deg * (Math.PI/180) 
    } 

    var getDistanceFromLatLonInMi = function(lat1, lon1, lat2, lon2) { 
    var R = 6371; // Radius of the earth in km 
    var dLat = deg2rad(lat2-lat1); // deg2rad below 
    var dLon = deg2rad(lon2-lon1); 
    var a = 
     Math.sin(dLat/2) * Math.sin(dLat/2) + 
     Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
     Math.sin(dLon/2) * Math.sin(dLon/2); 
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
    var d = R * c; // Distance in km 
    d = d * 0.621371; 
    return d; 
    }; 

    return { 
    fetchEvents: fetchEvents, 
    appendDistanceFromEvents: appendDistanceFromEvents 
    }; 
}); 

angular.module('controllers', []). 

controller('EventsController', ['$scope', '$controller', 'EventService', function($scope, $controller, EventService){ 
    EventService.fetchEvents().then(function(events){ 
    // real app is doing other stuff in here 
    // so would like to keep promise/then pattern 
    EventService.appendDistanceFromEvents(events).then(function(results) { 
     $scope.events = results; 
    }); 
    }); 
}]); 
Verwandte Themen