wake-up-neo.net

AngularJS-Bereich wird nach einem asynchronen Aufruf nicht aktualisiert

Ich habe Probleme beim Aktualisieren meines Bereichs im Frontend, während ich eine Anforderung an eine API erstelle. Im Backend kann ich sehen, dass sich der Wert meiner $ scope-Variablen ändert, was sich jedoch nicht in den Ansichten widerspiegelt.

Hier ist mein Controller.

Controllers.controller('searchCtrl', 
 function($scope, $http, $timeout) {
   $scope.$watch('search', function() {
      fetch();
   });

 $scope.search = "Sherlock Holmes";

 function fetch(){
   var query = "http://api.com/v2/search?q=" + $scope.search + "&key=[API KEY]&format=json";
    $timeout(function(){
      $http.get(query)
      .then(function(response){ 
        $scope.beers = response.data; 
        console.log($scope.beers);
      });
    });  
 }
});

Hier ist ein Ausschnitt aus meinem HTML

<div ng-if="!beers">
  Loading results...
</div>
<p>Beers: {{beers}}</p>
<div ng-if="beers.status==='success'">

  <div class='row'>
    <div class='col-xs-8 .col-lg-8' ng-repeat="beer in beers.data track by $index" ng-if="beer.style">
    <h2>{{beer.name}}</h2>          
    <p>{{beer.style.description}}</p>
    <hr>
    </div>
  </div>
</div>

<div ng-if="beers.status==='failure'">
  <p>No results found.</p>
</div>

Ich habe verschiedene Lösungen ausprobiert, ua mit $ scope. $ Apply (); aber dies erzeugt nur den allgemeinen Fehler

Fehler: $ digest ist bereits in Bearbeitung

Im folgenden Beitrag wird vorgeschlagen, $ timeout oder $ asyncDefault AngularJS zu verwenden: Verhindern, dass der Fehler $ digest bereits ausgeführt wird, wenn $ scope aufgerufen wird. $ Apply ()

Der Code, den ich oben verwendet habe, verwendet $ timeout und ich habe keine Fehler, aber die Ansicht wird nicht aktualisiert.

Hilfe geschätzt

13
peterpod

Wenn Sie AngularJS 1.3+ verwenden, können Sie $scope.$applyAsync() direkt nach der $scope.beers = response.data;-Anweisung versuchen.

Dies ist, was Angular Dokumentation über $applyAsync() sagt

Planen Sie den Aufruf von $ apply zu einem späteren Zeitpunkt. Der tatsächliche Zeitunterschied variiert von Browser zu Browser, beträgt jedoch normalerweise etwa 10 Millisekunden. Quelle

Update

Wie bereits erwähnt, sollten Sie den Digest-Zyklus (normalerweise) nicht manuell auslösen müssen. Meistens deutet dies lediglich auf ein schlechtes Design (oder zumindest kein AngularJS-freundliches Design) Ihrer Anwendung hin.

Derzeit wird im OP die fetch-Methode auf $ watch ausgelöst. Wenn diese Methode stattdessen von ngChange ausgelöst werden sollte, sollte der Digest-Zyklus automatisch ausgelöst werden.

Hier ein Beispiel, wie ein solcher Code aussehen könnte:

HTML

// please note the "controller as" syntax would be preferred, but that is out of the scope of this question/answer
<input ng-model="search" ng-change="fetchBeers()">

JavaScript

function SearchController($scope, $http) {

    $scope.search = "Sherlock Holmes";

    $scope.fetchBeers = function () {
        const query = `http://api.com/v2/search?q=${$scope.search}&key=[API KEY]&format=json`;
        $http.get(query).then(response => $scope.beers = response.data);
    };

}
11
Vladimir Zdenek

Hey Jungs, ich habe das Problem gelöst, aber ich weiß nicht genau, warum sich das geändert hat. Neuanpassung meines Codes in JS Fiddle Ich habe einfach alle meine Partials in die index.html-Datei eingefügt, und die Anforderungen und Bereichsvariablen wurden problemlos aktualisiert. Gab es vielleicht einen Controller-Konflikt mit meiner HTML-Datei oben?

<body ng-app="beerify" ng-controller='searchCtrl'>

<nav class="navbar navbar-inverse navbar-fixed-top">
  <div class="container"><!-- nav bar code -->
  </div>
</nav>

<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
  <div class="container">
    <h1>Title</h1>

    <form ng-submit="fetch()">
      <div class="input-group">
          <input type="text" ng-model="search" 
                 class="form-control" placeholder="Search the name of a beer" name="srch-term" id="srch-term">
          <div class="input-group-btn">
              <button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
          </div>
      </div>
    </form>

  </div>
</div>

<div class="container">

  <div ng-if="!beers">
    Loading results...
  </div>
  <div ng-if="beers.status==='success'">
   <div class='row'>
      <div class='col-xs-8 .col-lg-8' ng-repeat="beer in beers.data track by $index" ng-if="beer.style">
        <!-- ng-if will make sure there is some information being displayed
           for each beer -->
        <h2>{{beer.name}}</h2>
        <h3>{{beer.style.name}}</h3>
        <p>AbvMin: {{beer.abv}}</p>
        <p>AbvMax: {{beer.ibu}}</p>      
        <p>{{beer.style.description}}</p>
        <hr>
      </div>
    </div>
  </div>

  <div ng-if="beers.status==='failure'">
    <p>No results found.</p>
  </div>
</body>
0
peterpod

Wie aus den Kommentaren hervorgeht, sollten Sie nicht $timeout verwenden müssen, um einen Digest-Zyklus auszulösen. Solange sich die UX, die die Änderung hervorruft, innerhalb der confines eines Winkelkonstrukts (z. B. Controller-Funktion, Service usw.) befindet, sollte sie sich innerhalb des Digest-Zyklus manifestieren.

Basierend auf dem, was ich aus Ihrem Beitrag entnehmen kann, verwenden Sie wahrscheinlich eine Sucheingabe, um eine API mit Ergebnissen zu schlagen. Ich würde empfehlen, die Logik so zu ändern, dass Sie Ihre Suche nach einem expliziten Ereignis und nicht nach dem $watcher auslösen.

<input ng-model="search" ng-change="fetch()">

Entfernen Sie die $watch-Logik und den $timeout-Wrapper.

function fetch(){
    var query = "http://api.com/v2/search?q=" + $scope.search + "&key=[API KEY]&format=json";
$http.get(query)
.then(function(response){ 
    $scope.beers = response.data; 
    console.log($scope.beers);

    //it's a good habit to return your data in the promise APIs
    return $scope.beers;  
});
}

Die Gründe für diese Empfehlung sind:

  • Sie haben eine genauere Kontrolle darüber, wie der ng-change-Callback mit ng-model-options ausgelöst wird. Dies bedeutet, dass Sie eine Verzögerung einstellen können, Sie können für verschiedene UX-Ereignisse usw. auslösen.
  • Sie haben eine klarere Reihenfolge wie fetch aufgerufen wird.
  • Sie haben möglicherweise Leistungs- und $ Digest-Probleme vermieden.
0
jusopi