6

Ho raccolto un progetto e sto cercando di restituire alcuni dati da un servizio al mio controller. Sono stato a questo per circa 12 ore, e ho provato diversi metodi. Di solito portano a questo stesso tipo di "dati mancanti".AngularJS: l'ambito del controller non verrà sincronizzato con la promessa

Ho provato

  • utilizzando $ risorse invece di $ http
  • mettere il $http.get proprio all'interno del controllore senza utilizzare promesse
  • il servizio come un servizio effettivo (al posto di una fabbrica) senza un ritorno
  • costruzione della fabbrica un sacco di modi diversi per restituire i dati in una varietà di formati
  • utilizzando setTimeout e $ applicare

mi sento quello che ho adesso è una semplice come posso farlo, e tutto ciò che ho letto dice che questo dovrebbe funzionare

angularjs-load-data-from-service

angular-controller-cant-get-data-from-service

angularjs-promises-not-firing-when-returned-from-a-service

angularjs-promise-not-resolving-properly

angularjs-promise

Questi collegamenti erano solo da oggi.

ho pensato che ci potrebbe essere un problema di portata $, come in passato ho visto $ scopi non ottenere i dati quando più controllori abituarsi, tuttavia il sito dichiara semplicemente un controllore in index.html come <body ng-app="myApp" ng-controller="BodyCtrl"> setup. I principali app.js utilizza gli stati (da ui-router credo) in questo modo ...

.state('app.view', { 
    url: '/view', 
    templateUrl: 'views/view.tpl.html', 
    controller: 'MyCtrl' 
    }) 

per allegare controller per le diverse pagine. Inoltre, il sito ha alcuni altri controller che ottengono i dati dai servizi, che ho esaminato prima come modello, tuttavia i dati e i resi sono molto più complicati rispetto a quello che sto cercando di ottenere. In conclusione, i controllori stanno accedendo ai dati forniti dai servizi. Stanno tutti usando $ resource, che è il modo in cui ho iniziato con questo problema. Mi sono bloccato con $ http perché lo dovrebbe funzionare come e mi piacerebbe farlo funzionare prima di passare a qualcosa di "livello superiore". Inoltre, ho solo bisogno di ottenere dagli endpoint, quindi sentivo che la risorsa $ era eccessiva.

servizio

.factory('MyService', ['$http', '$q', '$rootScope', function ($http, $q, $rootScope) { 
    var defer = $q.defer(); 
    var factory = {}; 
    factory.all = function() { 
     $http({method: 'GET', url: 'http://URLtoJSONEndpoint'}). 
      success(function (data, status, headers, config) { 
       console.log('data success', data); 
       defer.resolve(data); 
      }). 
      error(function (data, status, headers, config) { 
       console.log('data error'); 
       defer.reject(data); 
      }); 

     return defer.promise; 
    }; 
    return factory; 
}]); 

regolatore

.controller('MyCtrl', ['$scope', '$state', '$stateParams', '$rootScope', 'MyService', '$q', function ($scope, $state, $stateParams, $rootScope, MyService, $q) { 
... 
... 
$scope.data = null; 
$scope.object = MyService; 
$scope.promise = MyService.all(); 

MyService.all().then(function (data) { 
    $scope.data = data; 
    console.log("data in promise", $scope.data); 
}) 
console.log("data", $scope.data); 
console.log("object", $scope.object); 
console.log("promise", $scope.promise); 

$http({method: 'GET', url: 'http://URL'}). 
     success(function (data, status, headers, config) { 
      $scope.data = data; 
      console.log('data success in ctrl', data); 
     }). 
     error(function (data, status, headers, config) { 
      console.log('data error'); 
     }); 

    console.log("data after ctrl", $scope.data); 


    angular.forEach($scope.data, function (item) { 
     // stuff that I need $scope.data for 
    } 

log della console

Quindi questo è il mio log della console, e posso arrivare a così MUC h, non solo i dati effettivi!Qual è ciò di cui ho bisogno. Sono persino diventato pazzo e ho esteso il mio .then(function (data) { per acquisire tutte le funzioni del controller che necessitano di $scope.data. Quello era un disastro ferroviario.

***data null*** 
object Object {all: function} 
promise Object {then: function, catch: function, finally: function} 
***data success after ctrl null*** 
data success in ctrl Array[143] 
data success Array[143] 
data in promise Array[143] 
data success Array[143] 

Per quanto posso dire, questo dovrebbe lavoro, ma non sono sicuro dove altro il problema può essere! Forse non capisco come le promesse funzionano o si risolvono. Ho usato Angular prima con un altro progetto, ma ero lì al suo inizio e ho capito come è stato messo insieme. Questo progetto è stato strutturato in modo diverso e si sente molto più caotico. Mi piacerebbe semplificarlo, ma non riesco nemmeno a recuperare alcuni dati semplici!

Apprezzo qualsiasi aiuto/feedback che puoi offrire per identificare il motivo per cui non funziona, grazie!

EDIT: Quindi la domanda è: perché è console.log("data", $scope.data) tornare null/prima della promessa?

un po 'più in basso nel controller ho questo

angular.forEach($scope.data, function (item) { 
// stuff 
} 

e non sembrano avere accesso ai dati.

EDIT2: ho aggiunto la $http.get stavo usando all'interno del controllore, insieme ai registri della console per esso e la realtà forEach ho bisogno $scope.data per

Edit3:

servizio aggiornato

.service('MyService', ['$http', function ($http) { 
    function all() { 
     return $http({ 
      url: 'http://URL', 
      method: 'GET' 
     }); 
    } 

    return { 
     all: all 
    } 
}]); 

controller aggiornato

MyService.all().success(function (data) { 
     $scope.data = data; 

     angular.forEach($scope.data, function (item) { 

      // Turn date value into timestamp, which is needed by NVD3 for mapping dates 
      var visitDate = new Date(item.testDate).getTime(); 

      switch (item.Class) { 
       case "TEST": 
        testData.push(
         [ 
          visitDate, 
          item.Total 
         ] 
        ); 

      } 

     }); 

     console.log("test Data in success", testData); 
    }); 


$scope.testData = [ 
     { 
      "key": "Test", 
      "values": testData 
     } 
    ]; 

Quindi $scope.testData deve essere utilizzato nella vista (grafico nvd3) e non riceve i dati.

SOLUZIONE

MyService.all().success(function (data) { 
     $scope.data = data; 

     angular.forEach($scope.data, function (item) { 

      // Turn date value into timestamp, which is needed by NVD3 for mapping dates 
      var visitDate = new Date(item.testDate).getTime(); 

      switch (item.Class) { 
       case "TEST": 
        testData.push(
         [ 
          visitDate, 
          item.Total 
         ] 
        ); 
      } 

     }); 

     console.log("test Data in success", testData); 

     $scope.testData = [ 
     { 
      "key": "Test", 
      "values": testData 
     } 
    ]; 
    }); 
+2

Quindi la tua domanda è, perché 'console.log ("dati", $ scope.data); // => data null'? Se sì, probabilmente è perché il log viene eseguito prima che la chiamata asincrona termini.Sidenote le due chiamate a 'MyService.all();' in realtà attiveranno due richieste. Penso che il primo non sia necessario. – Yoshi

+1

Sì, esattamente! Grazie per averlo sottolineato, non era molto chiaro – mykepwnage

+1

Avrei iniziato a farlo funzionare all'interno del controller, quindi in caso di successo do $ scope.data = data; Quando riesci a vedere la chiamata che funziona con successo, inizia a fare il refator con i servizi, pensa di aggiungere complessità. $ http restituisce già una promessa, quindi non è necessario utilizzare un'altra promessa. https://docs.angularjs.org/api/ng/service/$http – LightningShield

risposta

5

Questo potrebbe essere un esempio molto semplice di come il vostro servizio potrebbe essere simile:

app.service('MyService', ['$http', function ($http) { 
    function all() { 
    return $http({ 
     url: 'data.json', 
     method: 'GET' 
    }); 
    } 

    return { 
    all: all 
    } 
}]); 

Nel controllore lo si utilizza in questo modo:

app.controller('AppCtrl', ['$scope', 'MyService', function ($scope, MyService) { 
    $scope.data = null; 

    MyService.all().success(function (data) { 
    $scope.data = data; 

    // init further handling of `.data` here. 
    }); 
}]); 

Demo: http://plnkr.co/edit/l8pF8Uaa312A8kPtaCNM?p=preview


di rispondere alla domanda perché i log della console data null: questo è semplicemente perché il registro avviene prima del termine di chiamata asincrona.

0

Sono di fronte allo stesso problema. Risolvo che problema utilizzando $rootScope all'interno della promessa piuttosto che il $scope.So$rootScope.data sarà disponibile in console.log

Problemi correlati