2016-04-19 6 views
1

Wenn zwei aufeinanderfolgende Serviceanrufe über den $ http-Winkelservice bei der Dropdown-Elementauswahl getätigt werden und angenommen wird, dass der erste Anruf Zeit benötigt, um zurückzukehren, und zweiten Anruf zurückgibt, bevor der erste Anruf aufgelöst wird, zeigt er Daten des ersten Anrufs für die zweite Elementauswahl an.Wie kann ich die Zusage für den ersten Anruf während 2 aufeinander folgenden Serviceanrufen abbrechen/stornieren?

So ist es eine Möglichkeit, erste Versprechen abzubrechen, wenn Service-Aufruf wieder hergestellt vor dem ersten Anruf gelöst wird.

Für den Demo-Zweck habe ich Beispiel plunkar erstellt, die Drop-Down mit wenigen Elementen, die ich explizite Bedingung hinzugefügt, wo auf die Auswahl des ersten Elements dauerte etwas mehr Zeit als andere Elemente. Wählen Sie also das erste Element aus und wählen Sie sofort das zweite Element aus, um das Szenario zu reproduzieren. Überprüfen Sie die Anzeige der Favoriten auf dem Bildschirm.

Jede Hilfe wird geschätzt!

Servicecode:

app.factory('bookService', function($http, $q, $timeout) { 
    return { 
    getBook: function(id) { 
     var promise = $q.defer(); 
     var timeoutSpan = id == 1 ? 3000 : 500; 
     $http.get("favouriteBooks.json").success(function(data) { 
     $timeout(function() { 
      promise.resolve(data.filter(function(obj) { 
      return obj.id == id 
      })); 
     }, timeoutSpan); 
     }).error(function(msg) { 
     promise.reject(msg); 
     }) 
     return promise.promise; 
    } 
    } 
}); 
+0

sein kann [diese] (http://www.bennadel.com/blog/2616-aborting-ajax-requests-using-http- and-angularjs.htm) hilft Ihnen –

+0

Die zweite AJAX-Anfrage erst nach der Antwort der ersten Anfrage (Synchronisation Ihrer Anfrage) auszulösen. Um dies zu erreichen, können Sie das Dropdown-Menü mit einem Ladesymbol oder einem Bild deaktivieren, bis die Antwort für die erste Anfrage empfangen wird. Dies ist die eine Lösung, die Sie ausprobieren können. –

+0

Karthik, die Anforderung besteht nicht darin, den Benutzer daran zu hindern, aus Sicht der Benutzererfahrung Maßnahmen zu ergreifen. Dies ist die letzte Option, wenn dieses Problem nicht gelöst werden kann. –

Antwort

1

fand ich 2 Möglichkeiten, um dieses Szenario zu behandeln -

Fall 1: Erstellen Sie ein globales $ q deffer-Objekt auf Service-Ebene und prüfen Sie, ob dieses Objekt einen Wert hat (oder nicht), bevor Sie den Aufruf von $ http ausführen. Wenn dieses Deffer-Objekt einen Wert hat, wurde es explizit aufgelöst. Plunkar Code - code snippet

Servicecode:

app.factory('bookService', function($http, $q, $timeout, bookConstants) { 
    var service = {}; 
    service.mypromise = null; 

    service.getBook = function(id) { 
    if (service.mypromise) { 
     service.mypromise.resolve(bookConstants.EXPLICIT_CANCEL); 
     service.mypromise = null; 
    } 
    service.mypromise = $q.defer(); 
    var timeoutSpan = id == 1 ? 3000 : 500; 
    $http.get("favouriteBooks.json").success(function(data) { 
     $timeout(function() { 
     if (service.mypromise) { 
      service.mypromise.resolve(data.filter(function(obj) { 
      service.mypromise = null; 
      return obj.id == id 
      })) 
     } 
     }, timeoutSpan); 
    }).error(function(msg) { 
     service.mypromise.reject(msg); 
    }) 
    return service.mypromise.promise; 
    } 

    return service; 

}); 

Fall 2: Return $ q deffer Objekt als Service-Antwort und halten es auf Controller-Ebene. Und im Falle eines konsekutiven Dienstanrufs zuerst den ersten Dienstanruf überprüfen und dann explizit lösen und mit einem anderen Dienstanruf fortfahren. Plunkar Code - code snippet

Beispielcode:

$scope.getSelectedValue = function() { 
    var id = $scope.selitem.id 
    $scope.cancel(); 
    var bookPromise = bookService.getBook(id); 
    $scope.requests.push(bookPromise); 
    bookPromise.promise.then(getBookSuccess) 
     .catch(errorCallback) 
     .finally(getBookComplete); 
    } 

    function getBookSuccess(favouriteBooks) { 
    if (favouriteBooks == 'User Cancelled') { 
     return; 
    } 

    var books = ''; 
    angular.forEach(favouriteBooks, function(book) { 
     books += book.bookName + ' ' 
    }); 

    $scope.selectedvalues = 'Name: ' + $scope.selitem.name + 
     ' Id: ' + $scope.selitem.id + ' Favourite Book(s): ' + books; 
    } 

    function errorCallback(errorMsg) { 
    console.log('Error Message: ' + errorMsg); 
    } 

    function getBookComplete() { 
    console.log('getBook Has Completed!'); 
    } 

    $scope.cancel = function() { 
    if ($scope.requests) { 
     angular.forEach($scope.requests, function(request) { 
     request.resolve('User Cancelled'); 
     clearRequest(request); 
     }) 
    } 
    }; 

    var clearRequest = function(request) { 
    $scope.requests.splice($scope.requests.indexOf(request), 1); 
    }; 

}]); 

app.factory('bookService', function($http, $q, $timeout) { 
    var service = {}; 
    service.getBook = function(id) { 
    var promise = $q.defer(); 
    var timeoutSpan = id == 1 ? 3000 : 500; 
    $http.get("favouriteBooks.json").success(function(data) { 
     $timeout(function() { 
     promise.resolve(data.filter(function(obj) { 
      return obj.id == id 
     })) 
     }, timeoutSpan); 
    }).error(function(msg) { 
     promise.reject(msg); 
    }) 
    return promise; 
    } 
    return service; 
}); 
-1

Sie können die folgenden Befehle verwenden für zwei oder mehr Versprechungen warten $q.all([promise1,promise2]).then(function(data){....});

Um Daten der ersten Versprechen Zugriff verwenden nur data[0] das zweite Versprechen Rückgabewert wird in gespeichert und so weiter ...