调用服务函数:第一次执行时没有填充作用域

Call To Service Function: Not Populating Scope On First Execution

本文关键字:填充 作用域 执行 服务 函数 第一次 调用      更新时间:2023-09-26

我正在重构一些angularjs代码,以使控制器更精简,并将一些逻辑移动到服务中。

旧代码 This works OK.

在控制器…

var firmSearchRequest = {
    type : "ByDate",
    startDate : $scope.startDate,
    endDate : $scope.endDate
};
firmService.getFirms(firmSearchRequest).then(function(response) {           
    firmService.appendFirmList(response.data);          
    $scope.firmList = firmService.getFirmList();
});

服务……

var firmList = [];
    this.getFirms = function(firmSearchRequest) {
        return httpService.putForResponse('firms/search', firmSearchRequest);
    };

    this.appendFirmList = function(newfirmList){
        firmList = firmList.concat(newfirmList);
    }

    this.getFirmList = function() {
        return firmList;
    };

重构后的代码未按预期工作

在控制器…

var firmSearchRequest = {
    type : "ByDate",
    startDate : $scope.startDate,
    endDate : $scope.endDate
};
$scope.firmList = firmService.appendFirmListByDate(firmSearchRequest);

服务……

var firmList = [];
    this.appendFirmListByDate = function(firmSearchRequest){
        this.getFirms(firmSearchRequest).then(function(response) {          
            firmList = firmList.concat(response.data);
        });
        return firmList;
    };
    this.getFirms = function(firmSearchRequest) {
        return httpService.putForResponse('firms/search', firmSearchRequest);
    };

异常行为

对于重构的代码,当我单击执行上述代码的按钮时,我没有收到控制台错误,但$scope.firmList为空。当我再次单击按钮进行第二次执行时,$scope.firmList被正确填充。

为什么第一次执行不能正常工作?我做错了什么?

在你的控制器

$scope.firmList = firmService.appendFirmListByDate(firmSearchRequest);

这里的函数firmService.appendFirmListByDate()是一个简单的函数,将同步运行,因此值将立即返回,因此在这种情况下返回的值是名为firmList

的空数组

那么问题来了,为什么当你第二次点击按钮时你得到了正确的列表。

  • 当你第二次点击按钮时,数组var firmList = []中的值被插入,因为第一次运行的承诺,它是

    this.getFirms(firmSearchRequest).then(function(response) {          
        firmList = firmList.concat(response.data);
    });
    
  • 当你第二次点击按钮时,函数仍然同步运行,你得到第一步填充的值。

注意-所以每次你得到的值都是由上一步的承诺填充的

重要

  • 你不能这样重构你的代码

  • 制作一个瘦控制器并不意味着去掉它的承诺。这意味着业务逻辑不应该在那里。所以你的承诺应该在服务内部它应该返回一个承诺给控制器数据操作等应该在服务内部完成

从服务返回承诺

this.appendFirmListByDate = function(firmSearchRequest){
   return new Promise(function(resolve,reject){
        //if firmList contains data then just return it
        if(firmList.length!==0){
               resolve(firmList);
         }else{
            this.getFirms(firmSearchRequest).then(function(response) {          
               firmList = firmList.concat(response.data);
               resolve(firmList);
            }).catch(function(error){
                  reject(error);
            });
        }
    });
};

不是你试图返回firmList之前(技术上无论是否)的承诺完成?

你应该把return放在promise里面,或者返回promise。

可以使用callaback函数

this.appendFirmListByDate = function(firmSearchRequest, fct){
    this.getFirms(firmSearchRequest).then(function(response) {          
        fct(firmList.concat(response.data);)
    });
};
控制器

firmService.appendFirmListByDate(firmSearchRequest, function(result){
    $scope.firmList = result;
});