angularjs中的承诺不起作用

时间:2015-04-21 09:14:47

标签: javascript angularjs

我有一个工厂从我的后端获取数据:

as.factory("abbdata", function GetAbbData($http,$rootScope,$routeParams,$q) {   //$q = promise
            var deffered = $q.defer();
            var data = [];
            var abbdata = {};

            abbdata.async = function () {
                $http.get($rootScope.appUrl + '/nao/summary/' + $routeParams['id']).success(function(d) {
                data = d.abbData;
                deffered.resolve();
            });

            return deffered.promise;
        };

        abbdata.data = function() {
            return data;
        };

        return abbdata;
        });

在我的控制器中调用我的工厂:

abbdata.async().then(function() {
        $scope.abbData = abbdata.data(); //Contains data
    });

当我在服务电话外面console.log($scope.abbData)时,在下面,结果是未经解决的。为什么?我打电话后,$scope.abbData不应该包含我服务中的数据吗?

编辑:

firebug

5 个答案:

答案 0 :(得分:2)

您需要将应该返回的数据传递给resolve函数,如下所示:

deffered.resolve(data);

编辑: 要获取控制器中的数据,请执行以下操作:

abbdata.async().then(function(data) {
        $scope.abbData = data; //Contains data
    });

答案 1 :(得分:1)

为什么不首先从异步调用中返回该值?

您可以通过在工厂中附加成功处理程序并从中返回一个值来链接承诺,您可以将代码简化为:

as.factory("abbdata", function GetAbbData($http,$rootScope,$routeParams) {
    return {
        async: function () {
            return $http.get($rootScope.appUrl + '/nao/summary/' + $routeParams['id']).success(function(d) {
                return d.data.abbData;
            });
        }
     }
});

然后像

一样使用它
abbdata.async().then(function(data) {
    $scope.abbData = data; //Contains data
});

答案 2 :(得分:0)

如果您在服务电话之外console.log($scope.abbData),它应显示undefined,因为该电话是异步的。

abbdata.async().then(function() {
    $scope.abbData = abbdata.data(); //Contains data
});
console.log($scope.abbData) // this should show undefined

设置abbData后的console.log($scope.abbData)应显示数据

abbdata.async().then(function() {
    $scope.abbData = abbdata.data(); //Contains data
    console.log($scope.abbData) // this should show the data
});

修改

您可以使用服务电话中的abbData,例如

angular.module('myApp', []).controller('HomeCtrl', function($scope, abbdata){
    var updateUI;    
    $scope.abbData = [];

    abbdata.async().then(function() {
        $scope.abbData = abbdata.data(); //Contains data
        updateUI();
    });
    updateUI = function(){
        //do something with $scope.abbData
    }
});

编辑2

在回复您的查询时,我会做类似的事情,

angular.module('myApp', [])
.controller('JobsCtrl', function($scope, $jobService) {
    $scope.jobs = [];
    $jobService.all().then(function(jobs) {
        $scope.jobs = jobs;
    });
})
.service('$jobService', function ($q, $http) {
    return {
        all: function () {
            var deferred = $q.defer();
            $http({
                url: 'http://url',
                method: "GET"
            }).success(function (data) {
                deferred.resolve(data);
            }).error(function () {
                deferred.reject("connection issue");
            });
            return deferred.promise;
        }
    }    
});

关联视图

<body ng-app = "myApp">
    <div ng-controller = "JobsCtrl">
        <div ng-repeat="job in jobs track by job.id">
            <a href="#/tab/jobs/{{job.id}}" class="item item-icon-right">
                <h2>{{job.job_name}}</h2>
                <p>DUE DATE: {{job.job_due_date}}</p>
            </a>
        </div>
    <div>
</body>
  1. 这里的服务是一个返回一个promise的all函数,即它将在获取数据时通知。
  2. 在控制器中调用服务,一旦解决了服务调用,$ scope.jobs就会被解析后的数据分配。
  3. $ scope.jobs用于角度视图。一旦解析了作业数据,即分配了$ scope.jobs,视图就会更新。
  4. 希望这会有所帮助

答案 3 :(得分:0)

我看了一眼,我有两个想法:

  • 第一个理论:您的服务未定义。
  • 第二个理论:你需要运行$ scope。$ apply();

请参阅此fiddler:https://jsfiddle.net/Lgfxtfm2/1/

'use strict';
var GetAbbData = function($q) {   
//$q = promise
var deffered = $q.defer();
var data = [];
var abbdata = {};

abbdata.async = function () {
    setTimeout(function() {
        //1: set dummy data
        //data = [200, 201];
        //2: do nothing
        //
        //3: set data as undefined
        //data = undefined;
        deffered.resolve();
    }, 100);

    return deffered.promise;
};

abbdata.data = function() {
    return data;
};

return abbdata;
};
var abbdata = GetAbbData(Q)
abbdata.async().then(function() {
    console.log(abbdata.data()); //Contains data
});

我已经删除了很多依赖项,并且为了我自己的轻松而用Q替换了$ q。

在上面的例子中,我首先尝试使用虚拟数据运行代码,控制台输出预期数据,然后我尝试不分配数据,我得到一个空数组。这就是为什么我认为如果你看到&#39; undefined&#39;您必须明确将值设置为&#39; undefined&#39;。

除此之外,我还注意到你是通过直接从$ scope读取来测试结果的。我知道当不在角度范围内时,对$ scope对象进行操作不一定及时发生,并且键入$ scope。$ apply()通常会修复此问题。通常,当使用$ http时,angular使您保持在适当的范围内,但是您使用$ q创建自己的承诺,因此这可能是另一个潜在的问题。

最后,其他两个答案指出你没有以标准方式使用promises。虽然您的代码工作正常,但将数据直接设置到服务上并从那里检索它是不正常的。您可以通过简单地解决您希望使用then方法处理的数据来保持您的服务无状态,如Anzeo和Markus的答案所示。

我希望我能找到解决方案,祝你好运。

Dipun

答案 4 :(得分:0)

as.factory("abbdata", function GetAbbData($http,$rootScope,$routeParams,$q) {   //$q = promise
            var deffered = $q.defer();
            var data = [];
            var abbdata = {};

            abbdata.async = function () {
                $http.get($rootScope.appUrl + '/nao/summary/' + $routeParams['id']).success(function(d) {
                data = d.abbData;
                deffered.resolve(data);
            });

            return deffered.promise;
        };

        abbdata.data = function() {
            return data;
        };

        return abbdata;
        });