2014-11-05 13 views
18

Wie mache ich blockieren http Anfrage in AngularJS, so dass ich die $ HTTP-Antwort auf sehr nächste Zeile verwenden kann?Wie synchrone HTTP-Anfrage in eckig js

Im folgende Beispiel wird $http Objekt das Ergebnis auf die nächste Zeile nicht zurück, so dass ich dieses Ergebnis zu fullcalender() passieren kann, eine JavaScript-Bibliothek, weil $scope.data Leerwert zurückkehrt.

Dies ist der Beispielcode:

$http.get('URL').success(function(data){ 
    $scope.data = data; 
}); 

$.fullCalender({ 
    data: $scope.data 
}); 
+0

Gibt es eine Möglichkeit, dies zu vermeiden? Javascript ist single-threaded, und eine synchrone HTTP-Anfrage wird den GESAMTEN BROWSER blockieren, während er auf eine Antwort wartet. Dies sollte nicht Ihre bevorzugte Lösung sein. – GregL

+1

Könnten Sie nicht einfach den Aufruf von fullCalendar in den Erfolgsrückruf verschieben und Daten gleich dem Datenarg des Rückrufs setzen? – Scott

+0

Wenn ich Fullcalendar-Daten im Callback verwende, wird es nicht in der Vorlage angezeigt. – Dipak

Antwort

2

Sie können promises dafür verwenden.

hier ein Beispiel:

$scope.myXhr = function(){ 

    var deferred = $q.defer(); 

    $http({ 
     url: 'ajax.php', 
     method: 'POST', 
     data:postData, 
     headers: {'Content-Type': 'application/x-www-form-urlencoded'} 
     }) 
     //if request is successful 
     .success(function(data,status,headers,config){ 

      //resolve the promise 
      deferred.resolve('request successful'); 

     }) 
     //if request is not successful 
     .error(function(data,status,headers,config){ 
      //reject the promise 
      deferred.reject('ERROR'); 
     }); 

    //return the promise 
    return deferred.promise; 
} 

$scope.callXhrAsynchronous = function(){ 

    var myPromise = $scope.myXhr(); 

    // wait until the promise return resolve or eject 
    //"then" has 2 functions (resolveFunction, rejectFunction) 
    myPromise.then(function(resolve){ 
     alert(resolve); 
     }, function(reject){ 
     alert(reject)  
    }); 

} 
+1

Was ist der Grund, das Versprechen, das von '$ http' erstellt wurde, nicht zurückzugeben? Es ist eine schlechte Praxis, bestehende Versprechen in verschobenen zu wickeln –

+0

Weil das Versprechen, das von $ http erstellt wird async – stevemao

+63

Ich frage mich, warum dies als eine Antwort akzeptiert wurde. Das OP fragte nach ** synchron **, und Sie antworteten ** asynchron ** – KingJulian

2

Sie können nicht, werden Sie mit ihm durch Versprechungen viel brauchen, aber man konnte es so versuchen zu tun:

$http.get('URL').success(function(data){ 
    angular.copy(data, $scope.data); 
}); 

$.fullCalender({ 
    data: $scope.data 
}); 

aber die meisten Menschen tun würden, nur

$http.get('URL').success(function(data){ 
    $.fullCalender({ 
     data: data 
    }); 
}); 

Wenn was auch immer Ihr fullCalender Objekt nicht mit Asynchron-Daten funktioniert, müssen Sie möglicherweise es wickeln in etwas wie ng-if oder erzwingen es neu zu zeichnen, wenn die Daten geliefert wurden. Sie können auch erzwingen, dass der Controller nicht geladen wird, bis die Daten mithilfe der Routenauflösung geladen wurden.

1

Hier ist eine praktische Antwort, mit freundlicher Genehmigung von Benutzer Kirill Slatin, der die Antwort als Kommentar gepostet. Praktisches Anwendungsbeispiel am Ende der Antwort.

Wenn, wie ich, können Sie dieses Antwortobjekt als Rahmen Variable verwenden müssen, sollte diese Arbeit:

$http.get('URL').success(function(data){ 

$scope.data = data; 
$.fullCalender = $scope.data; 
$scope.$apply() 
}); 

$scope.$apply() was das Antwortobjekt wird bestehen bleiben, so dass Sie diese Daten verwenden können.

-

Warum würden Sie brauchen, um dies zu tun?

Ich hatte versucht, eine "bearbeiten" Seite für meine Rezepte App zu erstellen. Ich musste mein Formular mit den Daten des ausgewählten Rezepts füllen. Nachdem ich meine GET-Anfrage gemacht und die Antwortdaten an die $ scope.form übergeben habe, bekam ich nichts ... $scope.$apply() und Kirill Slatin half mir sehr. Prost Kumpel!

Hier ist das Beispiel aus meinen editRecipeController:

$http.get('api/recipe/' + currentRecipeId).then(
    function (data) { 
     $scope.recipe = data.data; 
     $scope.form = $scope.recipe; 
     $scope.$apply() 
    } 
); 

Hoffnung, das hilft!