所以我正在做一些promise
链,因为我需要一些代码运行同步。在我有两个嵌套forEach
之前,这一切都很好。在第一个forEach
之后,我展示了具有我想要迭代的下一个数组的实际对象。在那儿!但后来我尝试迭代该数组并且是undefined
?
vm.enviarEmail = function() {
var result = {};
var def = $q.defer();
def.promise
.then(function(result){
console.log("1");
return estacion.leerEstacionesInforiego()
.then(function(respuesta) {
angular.forEach(respuesta, function(est) {
est.latitud = $rootScope.dmsToddI(est.latitud);
est.longitud = $rootScope.dmsToddI(est.longitud);
});
result.estaciones = respuesta;
console.log("estaciones",result.estaciones);
return result;
}, function(respuesta) {
console.log("ERROR: obtención de las estaciones no realizada");
});
return result;
})
.then(function(result) {
console.log("2");
return user.leerUsuarios()
.then(function(respuesta) {
result.users = respuesta;
console.log("usuarios",result.users);
return result;
}, function(respuesta) {
console.log("ERROR: obtención de usuarios no realizada.");
});
return result;
})
.then(function(result) {
console.log("3");
angular.forEach(result.users, function(user) {
user.html = "<style>td {border:solid 1px;}</style><table><thead><tr><th>Parcela</th><th>Estación</th><th>Cultivo</th><th>Método de riego</th>"+
"<th>Fecha siembra</th><th>Fecha último riego</th><th>Recomendación</th></tr></thead><tbody>";
campo.leerParcelasPropietario(user.id)
.then(function(respuesta) {
user.parcelas = respuesta;
}, function(respuesta) {
console.log("ERROR: obtención de parcelas por usuario no realizada.");
});
});
console.log("parcelas",result);
return result;
})
.then(function(result) {
console.log("4");
angular.forEach(result.users, function(user) {
console.log(user,user.parcelas);
angular.forEach(user.parcelas, function(par) {
console.log("parcela",par.nombre);
var hoy = new Date(); // Fecha actual
// Obtener el cultivo de la parcela
campo.leerCultivo(par.cultivo)
.then(function(respuesta) {
par.cultivo = respuesta;
console.log(par);
}, function(respuesta) {
console.log("ERROR: obtención del cultivo no realizada");
});
// Obtener el método de riego de la parcela
campo.leerMetodoRiego(par.riego)
.then(function(respuesta) {
par.riego = respuesta;
}, function(respuesta) {
console.log("ERROR: obtención del método de riego no realizada");
});
// Calcular la estación cercana
var distMin = 99999999;
var x1 = new google.maps.LatLng(par.latitud,par.longitud);
angular.forEach(result.estaciones, function(est) {
var x2 = new google.maps.LatLng(est.latitud,est.longitud);
var distancia = google.maps.geometry.spherical.computeDistanceBetween(x1, x2);
if (distancia < distMin) {
distMin = distancia;
par.estacion = est;
}
});
// Cálculo de días desde el último riego
var fecha = new Date(Date.parse(par.consulta));
par.diasR = (hoy - fecha)/(1000*60*60*24); // En días y no milisegundos
// Cálculo del estado del cultivo
var fechaS = new Date(Date.parse(par.siembra));
par.diasE = (hoy - fechaS)/(1000*60*60*24);
if (par.diasE < 46)
par.estado = 'ini';
else if (par.diasE < 76)
par.estado = 'des';
else if (par.diasE < 96)
par.estado = 'med';
else
par.estado = 'fin';
});
});
return result;
})
.then(function(result) {
console.log("5");
angular.forEach(result.users, function(user) {
console.log("para obtener datos",result.users);
angular.forEach(user.parcelas, function(par) {
estacion.obtenerDatosInforiego(Math.round(par.diasR),par.estacion.indicativo,par.estacion.provincia)
.then(function(respuesta) {
par.datos = respuesta;
}, function(respuesta) {
console.log("ERROR: obtención de los datos de Inforiego no realizada");
});
});
});
return result;
})
.then(function(result) {
console.log("6");
angular.forEach(result.users, function(user) {
angular.forEach(user.parcelas, function(par) {
par.datos_totales = {et0: 0, etc: 0, pe: 0}; // Los datos totales obtenidos de los cálculos
angular.forEach(par.datos, function(diadatos) {
// Corrección de la temperatura media
diadatos.tempmedia = (diadatos.tempmax+diadatos.tempmin)/2;
// Cálculo de la presión atmosférica (kPa)
diadatos.presion = 101.3*Math.pow(((293-(0.0065*par.estacion.altitud))/293),5.26);
// Cálculo de la constante psicométrica (kPa/ºC)
diadatos.constante_psicometrica = diadatos.presion*0.000665;
// Cálculo de la presión de saturación de vapor a la temperatura del aire (max, med y min) (kPa)
var psvmax = 0.6108*Math.pow(2.7183,(17.27*diadatos.tempmax)/(diadatos.tempmax+237.3));
var psvmin = 0.6108*Math.pow(2.7183,(17.27*diadatos.tempmin)/(diadatos.tempmin+237.3));
var psvmed = (psvmax+psvmin)/2;
// Cálculo de la presión real de vapor (kPa)
diadatos.presion_real_vapor = (psvmed*diadatos.humedadmedia)/100;
// Cálculo de la pendiente de la curva de presión de vapor (kPa/ºC)
diadatos.pendiente_curva_presion = (4098*psvmed)/Math.pow((diadatos.tempmedia+237.3),2);
// Cálculo de la ET0
diadatos.et0 = ((0.408*diadatos.pendiente_curva_presion*diadatos.rn)
+(diadatos.constante_psicometrica*diadatos.velviento*900*(psvmed-diadatos.presion_real_vapor))/(273+diadatos.tempmedia))
/(diadatos.pendiente_curva_presion+(diadatos.constante_psicometrica*(1+0.34*diadatos.velviento)));
// Cálculo de la ETc
if (par.estado == 'ini') {
diadatos.etc = diadatos.et0*par.cultivo.coef_ini;
diadatos.kc = par.cultivo.coef_ini;
} else if (par.estado == 'des') {
diadatos.etc = diadatos.et0*par.cultivo.coef_des;
diadatos.kc = par.cultivo.coef_des;
} else if (par.estado == 'med') {
diadatos.etc = diadatos.et0*par.cultivo.coef_med;
diadatos.kc = par.cultivo.coef_med;
} else if (par.estado == 'fin') {
diadatos.etc = diadatos.et0*par.cultivo.coef_fin;
diadatos.kc = par.cultivo.coef_fin;
}
// Sumar para los totales
par.datos_totales.et0 = par.datos_totales.et0 + diadatos.et0;
par.datos_totales.etc = par.datos_totales.etc + diadatos.etc;
par.datos_totales.pe = par.datos_totales.pe + diadatos.pepmon;
});
par.datos_totales.rr = (par.datos_totales.etc-par.datos_totales.pe)/par.riego.coef_eficiencia;
user.html = user.html + "<tr><td>" + par.nombre + "</td><td>" + par.estacion.nombre + "</td>"+
"<td>" + par.cultivo.nombre + "</td><td>" + par.riego.nombre + "</td>"+
"<td>" + $filter('date')(par.siembra, 'dd-MM-yyyy') + "</td>"+
"<td>" + $filter('date')(par.consulta, 'dd-MM-yyyy') + "</td>"+
"<td><b>" + Math.round(par.datos_totales.rr) + "</b> l/m<sup>2</sup></td></tr>";
});
});
return result;
})
.then(function(result) {
console.log("7");
angular.forEach(result.users, function(user) {
if (user.usuario != 'jlmm') {
user.html = user.html + "</tbody></table><br><a href='http://localhost:8080/AgriWea/#!/'>AgriWea</a>";
$http.post('http://localhost:8100/sendmail', {params: {
from: 'AgriWea <jmariscan@dominio.es>',
to: user.email,
subject: 'Recomendación diaria de riego',
html: user.html}})
.then(function(respuesta) {
console.log("Email enviado correctamente",texto);
}, function(respuesta) {
console.log("Email no enviado", respuesta);
});
}
});
})
.catch(function (error) {
console.log(error);
});
def.resolve(result);
正如你所看到我有一个console.log
,这就是我得到的:
我当时认为对象可能是undefined
因为Angular中的异步,但在同一console.log
我可以看到数组存在但是如果我尝试访问它是undefined
。救命啊!
解
使用@trincot的代码,我减少了then
的数量,我只用了三个代码就完成了所有代码。谢谢大家!
答案 0 :(得分:0)
您声明您使用了一个promise链,因为您希望同步运行代码,但这是不可能的。 promise链的各个部分是异步执行的。函数的最后一行在任何then
回调之前执行。
此外,您不能指望函数调用返回电子邮件。目前,您的功能没有返回任何内容,因此当您调用该功能时,您将获得undefined
。
但即使你会回报一些东西,也许永远不会是结果。你最多可以回复一个承诺。
您需要接受异步行为,并继续使用该模式。因此,不要期望同步分配值。相反,请继续使用then
。
例如,您可以从立即解析的承诺开始,将空结果对象传递到链中:
vm.enviarEmail = function() {
$q.when({}).then(function(result) {
...
return result; // <-- don't forget to return the enriched value
})
.then(function(result) {
...
return result;
})
.then(function(result) {
...
return result;
})
.then(function(result) {
angular.forEach(result.users, function(user) {
console.log(user, user.parcelas);
angular.forEach(user.parcelas, function(par) {
...
});
});
return result; // <-- you need to return the promise
});
};
然后按如下方式使用它:
vm.enviarEmail().then(function (result) {
console.log(result); // keep with the async pattern
});