本文介绍了为什么我的观察者在同一个更改中被调用两次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在本地运行的 AngularJS 1.4* 应用程序(还没有).此应用由 Laravel 5.1 后端 RESTFul API 提供服务.

我必须制作这个代表包裹旅行的应用程序.一个包由天组成,从0到N天不等.每天都有一个服务列表,范围从 0 到 N 个服务.还有酒店.

我的 Laravel 应用程序从中使用的 Web 服务器为我提供了一个预先设置的包,其中包含一个天数列表:每个天数都有一个服务列表和一个酒店数据(到目前为止未使用).在响应中,我有一个包的属性列表(现在无关紧要)和一个名为 days_info 的天数数组.该响应被放入我的 PackageController 上的 $scope.package 中.PackageController 还声明了一个名为 packageBlock 的指令,该指令包含天数列表和包的其他一些数据.

<package-days-block></package-days-block>

<package-days-block> 指令中,我有另一个每天遍历内部服务列表.

<服务块></服务块>

这就是问题开始的地方:令我意外的是,我的 ServiceController 中现在有一个 $scope.service.因此,我开始根据自己的需要在 ServiceController 中通过 $scope.service 更改它.

$scope.service 有一个名为 service_id 的属性.我在它上面放了一个监听器/观察器,所以在 $scope.service.service_id 改变时,我要求另一个 service_table(保存有关服务的信息,它基于用户之前选择或更改的service_id),并将其放入$scope.service.table.

//服务控制器$scope.reloadServicesTable = function(service_id, service_day, date, paxes){MandatoryService.getServiceTable(service_id, service_day, date, paxes).然后(功能(服务数据){$scope.service.table = service_data;},...);

reloadServicesTableservice_id 变化的观察者上被调用.

//服务控制器$scope.$watch('service.service_id',//放置观察者以观察服务 ID 的变化.功能(新服务,旧服务){if( new_service === old_service )返回;$scope.reloadServicesTable($scope.service.service_id, $scope.service.service_day, $scope.day.date, $scope.package.paxes);});

问题从这里开始:当 service_id 只更改一次时,对服务表的请求会被调用两次.

为什么,上帝,为什么?!

在我的代码的另一部分,我从 PackageController 运行整个 days_info 数组并读取属性 price 的值> 在 service.table 中:service.table.price.在那里,我意识到有两个范围:一个是我处理的,另一个是我没有奇怪的想法来自哪里!

如果我将 console.log($scope); 放在通过 days_info 运行的方法中,我会为每个请求获得两个范围.此方法位于 PackageController 上.

知道为什么会这样吗?

P.S.:这是我的第一个 AngularJS 应用程序,所以,如果我把一些基本的东西搞砸了,请放轻松......

正如一位同事在评论中指出的那样,我的问题不是很可重复.可悲的是,我不能只把我有疑问的部分放在这里,因为我一点也不知道问题出在哪里!(我知道这没有多大帮助)

我从 Chrome 控制台截取了一些屏幕截图:

首先,请求改变了 service_id

如您所见,每个请求每次都被调用两次.这不是一次性的./api/service/{id}... 是对服务表信息的调用./api/service/by_route/origin/... 返回从一个城市到另一个(或同一个)城市的服务列表.一个不干扰另一个.

另一个图像是来自 PackageController $scope 的 console.log 的输出,在 service_id 被更改时.

如您所见,有两个不同的范围.b 作用域是 r 作用域的儿子.r 作用域也在 service_id?

上调用观察者

总价调用从不同的地方调用了两次,如下图所示:

解决方案

它可能会解决您的问题.就连我也遇到过和你说的一模一样的.

  1. 我的原因是,控制器再次初始化,其中编写了一个单独的 api 调用,用于最初加载页面.

  2. 也可能存在您在标记中分配了两次控制器的情况.

I have an AngularJS 1.4* application running locally (yet). This app is served by an Laravel 5.1 backend RESTFul API.

I have to make this app that represents a package trip. A package is composed by days, ranging from 0 to N days. Each day have a list of services, ranging from 0 to N services. And a hotel.

My web server, from which my laravel application consumes from, delivers me a pre-setted package, containing a list of days: each one with a list of services and a hotel data (unused so far). On the response I have a list of properties for the package (that don't matter for now) and an array of days, called days_info. That response is being put in the $scope.package, on my PackageController. The PackageController also declares an directive called packageBlock, that consists in a list of days, and some other data for the package.

<div ng-repeat="day in package.days_info" class='row'>
    <div class='col-md-12'>
        <package-days-block></package-days-block>
    </div>
</div>

Inside <package-days-block> directive, I have another to iterate through the list of services inside every day.

<div class='container-fluid' ng-repeat='service in day.services' ng-controller="ServiceController">
    <service-block></service-block>
</div>

That's where the problem begins: to my undestandment, I now have a $scope.service inside my ServiceController. So, I started to change it on my need inside the ServiceController through a $scope.service.

The $scope.service has an attribute called service_id. I put a listener/watcher on it, so at any time the $scope.service.service_id is changed, I ask for another service_table (holds the informations about the services, it's based on the service_id previously choosen or changed by the user), and put it in the $scope.service.table.

// ServiceController
$scope.reloadServicesTable = function(service_id, service_day, date, paxes){
    MandatoryService.getServiceTable(service_id, service_day, date, paxes)
    .then(
        function(service_data) {
            $scope.service.table = service_data;
        },
        ...
    );

The reloadServicesTable is called on the watcher for the service_id changes.

// ServiceController
$scope.$watch(
    'service.service_id', // Places the watcher to watch the changes on the service's ID.
    function(new_service, old_service) {
        if( new_service === old_service )
            return;

        $scope.reloadServicesTable($scope.service.service_id, $scope.service.service_day, $scope.day.date, $scope.package.paxes);

    }
);

The problem starts here: the request for the service's table is called twice when the service_id only changes once.

WHY, GOD, WHY?!

There's another part of my code where I, from the PackageController, run through the entire days_info array and reads the value of an attribute price inside the service.table: service.table.price. In there, I realise that there's two scope's: the one I handling and the other that I have no FREAKING IDEA where it came from!

If I put an console.log($scope); inside the method that runs through the days_info, I get two scopes for every request. This method is on the PackageController.

Any ideas why this is happening?

P.S.: It's my very first AngularJS application, so, take easy if I messed up on something basic...

EDIT:

As pointed out by an fellow on the comments, my question wasn't very reproducible. Sadly, I can't put here only the part I'm having doubts cause I don't have the slightest idea where the problem lies! (I know that this isn't much of help)

I took some screen shots from the Chrome Console:

First, the requestions fired on the change of the service_id

As you can see, every request is called twice everytime. This is not an one-time-thing. The /api/service/{id}... is the call for the service's table information. The /api/service/by_route/origin/... returns an list of services from one city to another (or the same). One does not interfere on the other.

The other image is the output from a console.log from the PackageController $scope, on the time that the service_id is being changed.

As you can see, there's two different scopes. And the b scope is son of the r scope. The r scope is also calling the watcher on the service_id?

The call for the sums price is been called twice from differente places, as you can see in the image below:

解决方案

It may solve you issue. Even i had faced exactly the same as you are mentioning.

  1. The reason for me was that, the controller was getting initialized again and there was a separate api call written in that, which was intended to load the page initially.

  2. There can also be a scenario where you have assigned controller twice in the mark up.

这篇关于为什么我的观察者在同一个更改中被调用两次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 18:05