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
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
}
];
});
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
Sì, esattamente! Grazie per averlo sottolineato, non era molto chiaro – mykepwnage
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