繁体   English   中英

如何强制此AngularJS服务等待它返回值?

[英]How can I force this AngularJS service to wait until it has a value to return?

我有一个被多个控制器调用的服务。 它将数据加载到对象categories

.service('DataService', ['$http', '$q', function($http, $q) {

    var categories = {};

    // Return public API.
    return({
        setCategory: setCategory,
        getCategory: getCategory,
        getJSON: getJSON,
        categories: categories
    });


    function setCategory(name, category) {
        console.log("setting category");
        console.log(name, category)
        categories[name] = category;
    }

    function getCategory(name) {
        console.log("getCategories:");
        console.log(categories[name]);
        return categories[name];
    }

    function getJSON() {
    //JSON stuff, where categories gets its initial values.
    }

我在很多地方都叫getCategory(name),在某些情况下,它是在categories填充之前被调用的,例如:

 $scope.category = DataService.getCategory(name);
 //$scope.category is undefined

我如何构建此服务,以便getCategories在返回值之前一直等到类别已定义? 或者,如何编写Controller以便在类别具有值之前不定义getCategories? 我尝试在控制器中使用$ scope。$ watch函数来监视DataService.categories,但没有成功-它从不记录更新后的值。

使用您已经在服务中注入的承诺。 这只是执行此操作的许多可能方式之一:

var pendingQueue = [];
var loaded = false;
var self = this;
function getCategory(name) {
    var deferred = $q.defer();

    if (loaded) {
        // Resolve immediately
        console.log('Already loaded categories, resolving immediately...');
        deferred.resolve(self.categories[name]);
        return deferred.promise;
    }

    // Queue the request
    pendingQueue.push({
        promise: deferred.promise,
        name: name
    });

    if (pendingQueue.length === 1) {
        console.log('First request for a category, requesting...

        // We are the FIRST request. Call whatever it takes to load the data.
        // In a 'real' language this wouldn't be thread-safe, but we only have one, so...
        $http.get('/my-data').then(function(data) {
            self.categories = data;
            console.log('Loaded categories', self.categories);
            loaded = true;

            pendingQueue.map(function(entry) {
                entry.promise.resolve(entry.name);
            });

            pendingQueue.length = 0;
        });
    }

    return deferred.promise;
}

然后在您的控制器中:

DataService.getCategory(name).then(function(category) {
    // Do something with category here
});

这将:

  • 对于第一个请求,请发出异步请求,然后在获取数据后解析承诺。

  • 对于第二个-第N个请求,在获取数据之前,对那些没有重复请求的请求进行排队。

  • 对于获取数据后的请求,请立即使用请求的数据进行解析。

没有错误处理可以完成-您应该使用deferred.reject()将其发送回调用方,并使用.catch()/ .finally()在控制器中进行处理。

解决方案有很多-这只是一种选择。

内部数据服务

yourApp.service('DataService', function($resource, $q) {
var resource = $resource('/api/category/:id', {}, {
    query: {
        method: 'GET',
        isArray: false,
        cache: false
    },
    save: {
        method: 'POST',
        isArray: false,
        cache: false
    }
});
return {
    getCategory: function(id) {
        var deferred = $q.defer();
        resource.query({id: id},
            function(response) {
                deferred.resolve(response);
            },
            function(response) {
                deferred.reject(response);
            }
        );
        return deferred.promise;
    },
    setCategory: function(categoryObj) {
        var deferred = $q.defer();
        resource.save(categoryObj,
            function(response) {
                deferred.resolve(response);
            },
            function(response) {
                deferred.reject(response);
            }
        );
        return deferred.promise;
    },
    getJSON: function() {
        // stuff to do
    }
};
});

内部DataController:

yourApp.controller('DataCtrl', function($scope, DataService) {

    $scope.handleSuccessResponse = function(response) {
        $scope.data = response;
    };

    $scope.handleErrorResponse = function(response) {
        $scope.error = response;
    };

    DataService.getCategory(123).then($scope.handleSuccessResponse, $scope.handleErrorResponse);
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM