AngularJS : 在循环中调用工厂方法
AngularJS : calling a factory method within the loop
我有一个如下所示的工厂方法:
angular.module('GridSamplesApp')
.factory('registerPostFactory', function($resource, $q, WebRequest) {
var getMessage = function(Upddata, token, dataurl)
{
var deferred = $q.defer();
var settings = {
data: Upddata,
headers: {
'Content-Type': 'application/JSON',
'x-csrf-token' : token
},
method: 'POST',
url: dataurl,
withCredentials: true
};
WebRequest.requestRaw(settings).then(
function(response) {
// data from app sec
var msg = response;
deferred.resolve(msg);
},
function(error) {
console.log('Error retrieving message', error);
deferred.reject('Error retrieving message', error);
});
return deferred.promise;
};
return {
getMessage: getMessage
};
});
我有一个看起来像
的控制器
$scope.getLogs = function()
{
$.each($scope.modifiedSN, function(i, e) {
if ($.inArray(e, result) == -1) result.push(e);
});
$scope.inputs.push({SN:'', Key:'', status:'', log:''});
for(var i=0; i<result.length; i++)
{
var j = result[i];
if ($scope.data[j].SerialNumber !== "")
{
var Upddata = {};
Upddata['IConvRuleFlg'] = '';
Upddata['SrNum'] = $scope.data[j].SerialNumber;
Upddata['LvEmailId'] = 'abc@xyz.com';
Upddata['WKey'] = $scope.data[j].WtyKey;
registerPostFactory.getMessage(Upddata, $scope.token, dataurl).then(
function(response) {
$scope.msg = response.headers["custommessage"];
$scope.data[j].AutolinkErrorlog = $scope.msg;
$scope.inputs.push({SN: $scope.data[j].SerialNumber, Key: $scope.data[j].WtyKey, status: response.headers["msgtype"], log: $scope.msg});
},
function(error) {
console.log('Error reading msg: ', error);
}
);
}
}
};
这个问题是它只接受数组中的最后一个元素,因为它是一个异步调用并且循环不会等待响应,我尝试使用 $q.all()
但无法弄清楚如何要实现这个,有人可以帮忙吗?
这里要用到闭包,我修改了你的代码,
(function(data) {
//console.log(data) //You can notice here, you are getting all individual loop objects
var Upddata = {};
Upddata['IConvRuleFlg'] = '';
Upddata['SrNum'] = data.SerialNumber;
Upddata['LvEmailId'] = 'abc@xyz.com';
Upddata['WKey'] = data.WtyKey;
registerPostFactory.getMessage(Upddata, $scope.token, dataurl).then(
function(response) {
$scope.msg = response.headers["custommessage"];
$scope.data[j].AutolinkErrorlog = $scope.msg;
$scope.inputs.push({
SN: data.SerialNumber,
Key: data.WtyKey,
status: response.headers["msgtype"],
log: $scope.msg
});
},
function(error) {
console.log('Error reading msg: ', error);
}
);
})($scope.data[j]);
据我了解,您的工厂工作正常,就像@RaviMone 所说的那样,在 for 循环中使用异步回调代码,您会惊讶于初学者经常掉入该陷阱。另外,我看到一个 $scope.msg
,不确定它来自哪里以及它是如何工作的,但是由于您的调用的异步和并行性质,它可能会为各种调用显示错误的值,如果它在每次调用时发生变化,您应该考虑序列化您的调用。
一种更简洁的写法 $scope.getLogs
可能是(我减少了 jQuery 的使用,使用了 ES5 的东西,如果你必须支持遗留系统,你可以使用 this ):
$scope.getLogs = function(){
var result = [] // again not sure where the result comes from, so initizing it here, else you can append filtered array to the previous set
$scope.modifiedSN.forEach(function(value) {
if (result.indexOf(value) < 0) result.push(e);
});
$scope.inputs.push({SN:'', Key:'', status:'', log:''});
var promises = result.map(function(val){
return $scope.data[val];
}).filter(function(val){
return val && val.SerialNumber !== ""; // first check if $scope.data[j] exists
}).map(function(val){
return registerPostFactory.getMessage({
IConvRuleFlg: '',
LvEmailId: '',
WKey: val.WtyKey,
SrNum: val.SerialNumber
}).then(function(response){
$scope.msg = response.headers["custommessage"];
val.AutolinkErrorlog = $scope.msg;
$scope.inputs.push({SN: val.SerialNumber, Key: val.WtyKey, status: response.headers["msgtype"], log: $scope.msg});
}).catch(function(e){
console.log('Error reading msg: ', e);
});
});
$q.all(promises)
.then(function(resArray){
console.log('get all logs...');
}).catch(function(e){
console.log('some error: ', e);
});
};
编辑:
如果您希望它们按顺序完成:
$scope.getLogs = function(){
var result = [] // again not sure where the result comes from, so initizing it here, else you can append filtered array to the previous set
, serialPromise = $q.when(1); // just initializing a promise.
$scope.modifiedSN.forEach(function(value) {
if (result.indexOf(value) < 0) result.push(e);
});
$scope.inputs.push({SN:'', Key:'', status:'', log:''});
result.map(function(val){
return $scope.data[val];
}).filter(function(val){
return val && val.SerialNumber !== ""; // first check if $scope.data[j] exists
}).forEach(function(val){
var datum = {
IConvRuleFlg: '',
LvEmailId: '',
WKey: val.WtyKey,
SrNum: val.SerialNumber
};
serialPromise = serialPromise.then(function(){ // adding a new promise to the chain.
return registerPostFactory.getMessage(datum);
}).then(function(response){
$scope.msg = response.headers["custommessage"];
val.AutolinkErrorlog = $scope.msg;
$scope.inputs.push({SN: val.SerialNumber, Key: val.WtyKey, status: response.headers["msgtype"], log: $scope.msg});
}).catch(function(e){
console.log('Error reading msg: ', e);
});
});
serialPromise.then(function(){
console.log('got all logs...');
}).catch(function(e){
console.log('some error: ', e);
});
};
我有一个如下所示的工厂方法:
angular.module('GridSamplesApp')
.factory('registerPostFactory', function($resource, $q, WebRequest) {
var getMessage = function(Upddata, token, dataurl)
{
var deferred = $q.defer();
var settings = {
data: Upddata,
headers: {
'Content-Type': 'application/JSON',
'x-csrf-token' : token
},
method: 'POST',
url: dataurl,
withCredentials: true
};
WebRequest.requestRaw(settings).then(
function(response) {
// data from app sec
var msg = response;
deferred.resolve(msg);
},
function(error) {
console.log('Error retrieving message', error);
deferred.reject('Error retrieving message', error);
});
return deferred.promise;
};
return {
getMessage: getMessage
};
});
我有一个看起来像
的控制器$scope.getLogs = function()
{
$.each($scope.modifiedSN, function(i, e) {
if ($.inArray(e, result) == -1) result.push(e);
});
$scope.inputs.push({SN:'', Key:'', status:'', log:''});
for(var i=0; i<result.length; i++)
{
var j = result[i];
if ($scope.data[j].SerialNumber !== "")
{
var Upddata = {};
Upddata['IConvRuleFlg'] = '';
Upddata['SrNum'] = $scope.data[j].SerialNumber;
Upddata['LvEmailId'] = 'abc@xyz.com';
Upddata['WKey'] = $scope.data[j].WtyKey;
registerPostFactory.getMessage(Upddata, $scope.token, dataurl).then(
function(response) {
$scope.msg = response.headers["custommessage"];
$scope.data[j].AutolinkErrorlog = $scope.msg;
$scope.inputs.push({SN: $scope.data[j].SerialNumber, Key: $scope.data[j].WtyKey, status: response.headers["msgtype"], log: $scope.msg});
},
function(error) {
console.log('Error reading msg: ', error);
}
);
}
}
};
这个问题是它只接受数组中的最后一个元素,因为它是一个异步调用并且循环不会等待响应,我尝试使用 $q.all()
但无法弄清楚如何要实现这个,有人可以帮忙吗?
这里要用到闭包,我修改了你的代码,
(function(data) {
//console.log(data) //You can notice here, you are getting all individual loop objects
var Upddata = {};
Upddata['IConvRuleFlg'] = '';
Upddata['SrNum'] = data.SerialNumber;
Upddata['LvEmailId'] = 'abc@xyz.com';
Upddata['WKey'] = data.WtyKey;
registerPostFactory.getMessage(Upddata, $scope.token, dataurl).then(
function(response) {
$scope.msg = response.headers["custommessage"];
$scope.data[j].AutolinkErrorlog = $scope.msg;
$scope.inputs.push({
SN: data.SerialNumber,
Key: data.WtyKey,
status: response.headers["msgtype"],
log: $scope.msg
});
},
function(error) {
console.log('Error reading msg: ', error);
}
);
})($scope.data[j]);
据我了解,您的工厂工作正常,就像@RaviMone 所说的那样,在 for 循环中使用异步回调代码,您会惊讶于初学者经常掉入该陷阱。另外,我看到一个 $scope.msg
,不确定它来自哪里以及它是如何工作的,但是由于您的调用的异步和并行性质,它可能会为各种调用显示错误的值,如果它在每次调用时发生变化,您应该考虑序列化您的调用。
一种更简洁的写法 $scope.getLogs
可能是(我减少了 jQuery 的使用,使用了 ES5 的东西,如果你必须支持遗留系统,你可以使用 this ):
$scope.getLogs = function(){
var result = [] // again not sure where the result comes from, so initizing it here, else you can append filtered array to the previous set
$scope.modifiedSN.forEach(function(value) {
if (result.indexOf(value) < 0) result.push(e);
});
$scope.inputs.push({SN:'', Key:'', status:'', log:''});
var promises = result.map(function(val){
return $scope.data[val];
}).filter(function(val){
return val && val.SerialNumber !== ""; // first check if $scope.data[j] exists
}).map(function(val){
return registerPostFactory.getMessage({
IConvRuleFlg: '',
LvEmailId: '',
WKey: val.WtyKey,
SrNum: val.SerialNumber
}).then(function(response){
$scope.msg = response.headers["custommessage"];
val.AutolinkErrorlog = $scope.msg;
$scope.inputs.push({SN: val.SerialNumber, Key: val.WtyKey, status: response.headers["msgtype"], log: $scope.msg});
}).catch(function(e){
console.log('Error reading msg: ', e);
});
});
$q.all(promises)
.then(function(resArray){
console.log('get all logs...');
}).catch(function(e){
console.log('some error: ', e);
});
};
编辑:
如果您希望它们按顺序完成:
$scope.getLogs = function(){
var result = [] // again not sure where the result comes from, so initizing it here, else you can append filtered array to the previous set
, serialPromise = $q.when(1); // just initializing a promise.
$scope.modifiedSN.forEach(function(value) {
if (result.indexOf(value) < 0) result.push(e);
});
$scope.inputs.push({SN:'', Key:'', status:'', log:''});
result.map(function(val){
return $scope.data[val];
}).filter(function(val){
return val && val.SerialNumber !== ""; // first check if $scope.data[j] exists
}).forEach(function(val){
var datum = {
IConvRuleFlg: '',
LvEmailId: '',
WKey: val.WtyKey,
SrNum: val.SerialNumber
};
serialPromise = serialPromise.then(function(){ // adding a new promise to the chain.
return registerPostFactory.getMessage(datum);
}).then(function(response){
$scope.msg = response.headers["custommessage"];
val.AutolinkErrorlog = $scope.msg;
$scope.inputs.push({SN: val.SerialNumber, Key: val.WtyKey, status: response.headers["msgtype"], log: $scope.msg});
}).catch(function(e){
console.log('Error reading msg: ', e);
});
});
serialPromise.then(function(){
console.log('got all logs...');
}).catch(function(e){
console.log('some error: ', e);
});
};