2017-01-24 3 views
2

Ich habe das folgende Code-Muster, wobei ein Update-Aufruf jedes Mal vorgenommen wird, wenn der Benutzer die Daten in der Ansicht aktualisiert.Zweiter Aufruf zum Versprechen wird ausgeführt, bevor das Versprechen zurückkehrt - Angular Javascript

// FACTORY SERVICE CODE 
.factory('updateService', ['$http', '$q', function($http, $q){ 
    var df = $q.defer(); 
    var updateData = function(uriName, dataObj){ 
     $http({ 
      method: 'PUT', 
      data: dataObj, 
      url: uriName 
      }).then(function successCallback(response) { 
       console.log('from put'); 
       console.log(response.data); 
       df.resolve(response.data); 
      }, function errorCallback(response) { 
       console.log('Error', response.data); 
       df.reject(response.data); 
     }); 
     return df.promise; 
    } 
    return {updateData:updateData}; 
}]) 

// CONTROLLER CODE 
.controller('MainCtrl', ['$scope','updateService', function($scope, updateService) { 
    $scope.saveToServer = function(){ 
     var tmpObj = {data: $scope.dataOne, anotherData: $scope.dataTwo}; 
     myService.updateData(uriName, tmpObj).then(function(resolved) { 
      console.log('CONTROLLER'); 
      $scope.myData = resolved; 
      console.log($scope.myData); 
      console.log('end'); 
     }, function(rejected){ 
      console.log('put rejected'); 
     }); 
    }); 
    $scope.btnUpdateClick = function(){ 
     $scope.saveToServer(); 
    }; 
}]); 

PROBLEM: Wenn der Benutzer eine Aktualisierungsanforderung zum ersten Mal macht, funktioniert der Code wie erwartet. Aber wenn der Benutzer danach aktualisiert, führt der "aufgelöste Versprechen" -Code (im Controller) FIRST aus und dann wird der $ http-Code (im Service) ausgeführt.

Beispiel für die Ausgabe von btnUpdateClick gemacht ZWEIMAL mit genügend Abstand in-between:

from put 
Array [ Object, Object] 
CONTROLLER 
Array [ Object, Object] 
end 
CONTROLLER 
Array [ Object, Object] 
end 
from put 
Array [ Object, Object] 

FRAGE: bitte ich darauf hinweisen, wo ich einen Fehler mache?

Ist das Problem wegen PUT Anfrage?

oder ist es möglich, die Ausführungswarteschlange wie erwartet zu korrigieren, durch $ apply oder ähnliches?

+0

'var df = $ q.defer(); 'verschiebe diesen Code in die' updateData'-Funktion und ein anderer Vorschlag ist, warum du separate Versprechen für $ http-Aufruf erstellst. Gib einfach das $ http Versprechen zurück. –

+0

@ pragaas wäre es besser, die Antwort nach dem Upvoting zu akzeptieren :) –

+0

@ARUN - zu Recht hingewiesen. – Mikki

Antwort

1

Sie starten jedes Mal das Versprechen unten eine Funktion wie nennen:

.factory('updateService', ['$http', '$q', function($http, $q){ 

    var updateData = function(uriName, dataObj){ 
     var df = $q.defer(); //Changes here 
     $http({ 
      method: 'PUT', 
      data: dataObj, 
      url: uriName 
      }).then(function successCallback(response) { 
       console.log('from put'); 
       console.log(response.data); 
       df.resolve(response.data); 
      }, function errorCallback(response) { 
       console.log('Error', response.data); 
       df.reject(response.data); 
     }); 
     return df.promise; 
    } 
    return {updateData:updateData}; 
}]) 

Auf diese Weise können Sie auf jedem Funktionsaufruf ein neues Versprechen erstellen.

0

Ihren Code ändern:

// FACTORY SERVICE CODE 
.factory('updateService', ['$http', '$q', function($http, $q){ 
    var updateData = function(uriName, dataObj){ 
     var df = $q.defer(); 
     $http({ 
      method: 'PUT', 
      data: dataObj, 
      url: uriName 
      }).then(function successCallback(response) { 
       console.log('from put'); 
       console.log(response.data); 
       df.resolve(response.data); 
      }, function errorCallback(response) { 
       console.log('Error', response.data); 
       df.reject(response.data); 
     }); 
     return df.promise; 
    } 
    return {updateData:updateData}; 
}]) 

// CONTROLLER CODE 
.controller('MainCtrl', ['$scope','updateService', function($scope, updateService) { 
    $scope.saveToServer = function(){ 
     var tmpObj = {data: $scope.dataOne, anotherData: $scope.dataTwo}; 
     myService.updateData(uriName, tmpObj).then(function(resolved) { 
      console.log('CONTROLLER'); 
      $scope.myData = resolved; 
      console.log($scope.myData); 
      console.log('end'); 
     }, function(rejected){ 
      console.log('put rejected'); 
     }); 
    }); 
    $scope.btnUpdateClick = function(){ 
     $scope.saveToServer(); 
    }; 
}]); 

In Ihrem alten Code, den Sie Objekt nur einmal aufzuschieben war die Schaffung so dass es nur einmal aufgelöst/abgelehnt wurde. Aber was Sie brauchen, ist, jedes Mal ein Versprechen abzugeben und es jedes Mal zu lösen/abzulehnen.

+0

"ändern Sie Ihren Code zu" - warum? was war falsch? –

+3

Code-only-Antworten sind nicht sehr nützlich. Erkläre, was repariert werden muss. – Pointy

+0

Haben Sie Geduld @Pointy –

3

Es gibt keine Notwendigkeit, ein benutzerdefiniertes Versprechen hier zu erstellen, obwohl es als schlechte Praxis gilt.

Ist das Problem wegen PUT Anfrage?

Es ist kein Problem im Zusammenhang mit PUT Anfrage. Ihre Factory verwendet das gemeinsame Objekt deferred und das gleiche wurde von der Methode zurückgegeben. Sobald das promise Objekt aufgelöst wird, befindet es sich immer im auflösenden Zustand.


Eher würde Ich mag Ihnen vorschlagen $http.put Versprechen zu nutzen, und Ihr Code kleiner machen als das, was Sie vorher hatten.

var updateData = function(uriName, dataObj){ 
    return $http.put(uriName,dataObj) 
} 
+0

Ihr Ansatz der Codierung ist absolut richtig. Aber da meine Frage eine Fehlerbehebung für den Fehler war, den ich in meinem Code hatte, würde ich gerne die andere Lösung als eine Antwort haben, nur für die Aufzeichnung. Gute Arbeit! – Mikki

4

Sie verwenden die "explicit promise creation antipattern" hier, und obendrein, versuchen, ein einziges aktives latentes Objekt unter alle Ihren Service-Anrufen zu teilen.

Nehmen Sie einfach loswerden der latenten und profitieren Sie von Verkettungs Eigenschaften verspricht und alles wird gut:

.factory('updateService', ['$http', '$q', function($http, $q){ 
    var updateData = function(uriName, dataObj){ 
     return $http({ 
      method: 'PUT', 
      data: dataObj, 
      url: uriName 
     }) 
     .then(function successCallback(response) { 
      console.log('from put'); 
      console.log(response.data); 
      return response.data; 
     }) 
     .catch(function errorCallback(response) { 
      console.log('Error', response.data); 
      throw response.data; 
     }); 
    }; 

    return {updateData:updateData}; 
}]); 
+0

Ihr Ansatz der Codierung ist absolut richtig. Aber da meine Frage eine Fehlerbehebung für den Fehler war, den ich in meinem Code hatte, möchte ich diese Lösung als eine Lösung haben, nur für die Aufzeichnung. Gute Arbeit! – Mikki

+0

so sehr, sehr absolut –

Verwandte Themen