2013-07-04 6 views
11

I eine Winkel Anwendung, die den Wert von einer Controller-Methode durch einen einfachen Ausdruck Bindung zurück zeigt:Endlosschleife mit kantigem Ausdruck Bindung

<div>{{getValue()}}</div> 

Wenn die Methode in Frage, nur einen Wert zurückgibt, wird die Methode aufgerufen zweimal, und das ist seltsam genug:

$scope.getValue = function(){ 
    return 'some value'; 
} 

Aber wenn das Verfahren einige asynchrone funktionierts wie eine Datei vom Server erhalten, geht der Code in eine Endlosschleife:

$scope.getValueAsync = function(){ 
    $http.get('myfile.html') 
    .success(function (data, status, headers, config) { 
     return 'some async value'; 
    }); 

    return 'file not found'; // same value returned every time but $digest cycle still loops 
} 

Ich bin neu in Angular, also habe ich wahrscheinlich etwas Grundlegendes verpasst, aber kann mir bitte jemand erklären, was vor sich geht?

Plunker

Hier ist ein Plunker spielen http://plnkr.co/7BriYDbdVJvIoIigQcTU

+0

Ja, ich denke das erklärt es wahrscheinlich, danke. Die getValueAsync-Methode in meinem Beispiel gibt jedoch immer denselben Wert zurück, sodass ich nicht erkennen kann, warum Angular es für weiterhin unbegrenzt aufrufen würde. –

Antwort

16

Auch wenn Ihre async Funktion jedes Mal exakt das gleiche Zeichenfolge zurückgibt, die $ verdauen Zyklus in Schleifen gefeuert wird, weil Ihre Funktion macht auch eine Ajax Anruf mit $ http-Service.

$ HTTP-Dienst löst $rootScope.$apply()when requests are completed und seit $apply einen verdauen Zyklus $ löst es macht Ihre Ansicht Ausdruck neu bewertet werden, was im Gegenzug bewirkt, dass Ihre Asynchron-Funktion erneut aufgerufen werden, und so weiter ...

app.controller('MainCtrl', function($scope, $http) { 

    $scope.getValue = function(){ 
    return 'some value'; 
    } 

    $scope.getValueAsync = function(){ 
    $http.get('myfile.html') 
     .success(function (data, status, headers, config) { 
     return 'some async value'; 
     }); 

    return 'file not found'; 
    } 
}); 
<div>{{getValueAsync()}}</div> 

Moral der Geschichte: Wenn Sie Funktionen in Ausdrücken verwenden, stellen Sie sicher, dass Ihre Funktionen wirken sich nicht auf etwas außerhalb von ihnen, die eine $ verdauen Schleife auslösen würde, und stellen Sie sicher, dass Ihre Funktionen immer die gleiche Rück Ausgabe bei gleicher Eingabe.

+0

Danke. Dies scheint ziemlich esoterisch - sogar unintuitiv - zu sein, obwohl ich vielleicht sehen kann, warum es notwendig ist, Angulars Anspruch auf Ruhm für eine Zweiwege-Bindung zu erfüllen. –

+0

Ein anderer Kommentar, die Richtlinie, die Sie effektiv geben, bedeutet, dass Ansichten niemals an Funktionen gebunden sein sollten, wenn die Funktionen Versprechungen intern verwenden. Das ist in den Angular-Dokumenten wirklich wichtig. –

+1

In der Tat würde ich weiter gehen! $ http.get() ist eine klassische Funktion und sollte solche Nebenwirkungen nicht haben. -1 für Angular. –

0

Ich habe das gleiche Problem wie Sie, um das Problem zu beheben, können wir die Ergebnisse der Funktion zwischenspeichern. Zu diesem Zweck bevorzuge ich die Memoize-Funktion von Lo-Dash. Ich erstelle eine Demo, um Ihnen zu zeigen, wie ich dieses Problem beheben konnte. The following link contains the demo:http://plnkr.co/edit/KBmk4J2ZCt0SsmZlnKZi?p=preview