如何在服务中使用异步库

How to use async library in a service?

本文关键字:异步 服务      更新时间:2023-09-26

我正在尝试在我的服务中使用异步库。最后,我计划执行一系列$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
}]);

更好的方法是使用$q,它是angular的promise系统。如果你使用它,就不需要另一个第三方依赖的额外膨胀。

您的服务将只是:

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()是如何在触发前等待超时结束的。

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


EDIT:而且您的初始服务无论如何都不会运行,它会抛出语法错误。

这可能是你的冒犯之处(减去你服务中丢失的return {}部分,但我猜这是将代码复制到SO中的错误):

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

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

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

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

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);
})