如何在服务中使用异步库?
How to use async library in a service?
我正在尝试在我的服务中使用异步库。最终我计划进行一系列 $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
}]);
您的 console.log 打印输出需要等到 async.series 中的所有调用都完成。更改您的函数调用以获取回调,并在完成后打印 return 值:
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);
})
更好的方法是使用 $q
它是 angular 的承诺系统。如果您使用它,则不需要另一个第三方依赖项的额外膨胀。
您的服务将是:
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
编辑:你的初始服务也不会有 运行 无论如何它会抛出语法错误。
这本来是你的冒犯点(减去你服务中缺失的 return {}
部分,但我猜这是将代码复制到 SO 中的错误):
// optional callback
return function(err, results){
return results;
});
JavaScript 不是这样的。您不能在该上下文中使用 return
关键字。您将变量传递给一个方法,async.series
,第一个是数组,第二个是回调,一旦您在每个数组函数中调用 done 回调就完成。
async.series
没有 return 值。我不能,因为它对数组方法的执行是异步的。
我正在尝试在我的服务中使用异步库。最终我计划进行一系列 $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
}]);
您的 console.log 打印输出需要等到 async.series 中的所有调用都完成。更改您的函数调用以获取回调,并在完成后打印 return 值:
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);
})
更好的方法是使用 $q
它是 angular 的承诺系统。如果您使用它,则不需要另一个第三方依赖项的额外膨胀。
您的服务将是:
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
编辑:你的初始服务也不会有 运行 无论如何它会抛出语法错误。
这本来是你的冒犯点(减去你服务中缺失的 return {}
部分,但我猜这是将代码复制到 SO 中的错误):
// optional callback
return function(err, results){
return results;
});
JavaScript 不是这样的。您不能在该上下文中使用 return
关键字。您将变量传递给一个方法,async.series
,第一个是数组,第二个是回调,一旦您在每个数组函数中调用 done 回调就完成。
async.series
没有 return 值。我不能,因为它对数组方法的执行是异步的。