如何在服务中使用异步库?

时间:2015-10-30 03:11:51

标签: javascript angularjs asynchronous angular-services

我正在尝试在我的服务中使用异步lib。最终我计划进行一系列$ resource.query()调用并将结果传递给阶梯。

我遇到的问题是让我的console.log()等待异步系列完成。如何设置我的async_service.async_func()调用以使其异步,以便等待所有控制器函数在运行之前完成?

  angular.module('app.services').factory('async_service', ['$resource',
  function($resource) {

 async_func:function(){

                return async.series([
                    function(callback){
                        //will do  a $resource.query() call eventually
                        callback(null, 'one');
                    },
                    function(callback){
                        //will do  a $resource.query() call eventually
                        callback(null, 'two');
                    }
                ],
                // optional callback
                return function(err, results){
                    return results;
                });
        }
}]);


angular.module('app.controllers', []) .controller('AppCtrl', ['$scope','async_service', function($scope, async_service) {

    var v = async_service.async_func();
    console.log(v);  //should be ['one', 'two'] but getting undefined

}]);

2 个答案:

答案 0 :(得分:0)

你的console.log打印输出需要等到async.series中的所有调用都完成。更改函数调用以获取回调,并在完成后打印返回值:

async_func:function(cb) {

            return async.series([
                function(callback){
                    //will do  a $resource.query() call eventually
                    callback(null, 'one');
                },
                function(callback){
                    //will do  a $resource.query() call eventually
                    callback(null, 'two');
                }
            ],
            // optional callback
            function(err, results){
                return cb(err, results);
            });
    }
}]);

async_service.async_func(function(err, results) {
   if (!err)
       console.log(results);
})

答案 1 :(得分:0)

更好的方法是使用$q它是有角度的承诺系统。如果您使用它,则不需要额外的第三方依赖。

您的服务只是:

angular.module('app.services').factory('async_service', ['$resource', '$q',
    function($resource, $q) {
        return {
            async_func: function() {

                return $q.all(['one','two', this.hitApi()]);
            },
            hitApi: function () {
                /*
                    Simulate api call, 
                    $timeout returns a promise which is resolved when the timeout is met.
                    Same as $http
                */
                return $timeout(function(){ return 'three'}, 1000);
            }
        }
    }
]);

并将其用作

async_service.async_func().then(function (v) {
    /*
        .then() here will be called once all values/promises passed to $q.all have been resolved.
        If it receieves a promise it will wait untill those promises have been resolved.
        This would make it even easier if yo wish to do network calls as they return promises.
    */
    console.log(v);  //Will be ['one', 'two'] 
});

有一点需要注意。 $q.all将不会执行函数。它只是在承诺中包含价值观。如果该值恰好已经是一个承诺,它将在解决之前等待它解决。这就是为什么我添加了hitApi()方法,以便您可以看到如何实现该行为。另请注意控制器中的.then()如何在触发前等待超时完成。

见小提琴:http://jsfiddle.net/rjLshbz5/1/ 请参阅文档:https://docs.angularjs.org/api/ng/service/ $ q

编辑:此外,您的初始服务无论如何都会运行它会抛出语法错误。

这可能是您的违规行(减去服务中缺少的return {}部分,但我猜这是将代码复制到SO中的错误):

            // optional callback
            return function(err, results){
                return results;
            });

JavaScript并不像那样工作。您无法在该上下文中使用return关键字。您将变量传递给方法async.series,第一个是数组,第二个是在每个数组函数中调用完成回调后完成的回调。

async.series没有返回值。我不能因为它的数组方法的执行是异步的。