AngularJS的作用域在异步调用后没有在视图中更新。

28 浏览
0 Comments

AngularJS的作用域在异步调用后没有在视图中更新。

在请求API时,我在前端更新$scope时遇到了问题。在后端中,我可以看到我的$scope变量的值正在变化,但是这并没有反映在视图中。

以下是我的控制器。

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);
      });
    });  
 }
});

这是我HTML代码的片段

  Loading results...

Beers: {{beers}}

 

{{beer.name}}

 

{{beer.style.description}}

 


 

No results found.

 

我尝试了几种解决方案,包括使用$scope.$apply();,但这只会创建常见错误

错误:$digest已经在进行中

以下帖子建议使用$timeout或$asyncDefault

AngularJS : Prevent error $digest already in progress when calling $scope.$apply()

我以上的代码使用了$timeout,我没有错误,但是视图仍然没有更新。

感谢您的帮助。

admin 更改状态以发布 2023年5月21日
0
0 Comments

正如评论中所指出的,您不应该需要使用$timeout来触发一个digest周期。只要触发变化的UX处于angular结构的限制范围内(例如控制器函数,服务等),它就应该在digest周期中体现。

根据我从您的帖子中可以推断出的信息,您可能正在使用搜索输入来命中API并获取结果。我建议更改逻辑,以便您在显式事件上触发搜索,而不是$watcher上。


删除$watch逻辑和$timeout包装器。

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;  
});
}

我推荐这样做的原因是:

  • 您可以使用ng-model-options更精细地控制ng-change回调的触发。这意味着您可以对其进行延迟,可以针对各种UX事件触发等。
  • 您保留了调用fetch的更清晰的顺序。
  • 您可能已避免了性能和$digest问题。
0
0 Comments

如果你正在使用AngularJS 1.3+,在 $scope.beers = response.data; 语句之后可以尝试使用 $scope.$applyAsync()。\n\n关于 $applyAsync() ,Angular文档如下所述:\n\n安排$apply在以后的某个时间调用。实际的时间差异在不同的浏览器中变化,但通常大约是10毫秒左右。\n\n更新\n\n正如其他人所指出的,通常不需要手动触发脏检查(digest cycle),因为它通常只是指向你的应用程序设计不良(或至少不适合AngularJS的设计)。\n\n目前,在原始帖子(OP)中,fetch方法是由$watch触发的。如果相反,该方法是由ngChange触发的,则应自动触发脏检查。\n\n以下是示例代码:\n\nHTML\n\n

// please note the "controller as" syntax would be preferred, but that is out of the scope of this question/answer

\n\nJavaScript\n\n

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);
    };
}

0