AngularJS承诺。存在的未定义数组

时间:2017-11-13 19:47:17

标签: javascript arrays angularjs promise

所以我正在做一些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,这就是我得到的:

enter image description here

我当时认为对象可能是undefined因为Angular中的异步,但在同一console.log我可以看到数组存在但是如果我尝试访问它是undefined 。救命啊!

使用@trincot的代码,我减少了then的数量,我只用了三个代码就完成了所有代码。谢谢大家!

1 个答案:

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