代码之家  ›  专栏  ›  技术社区  ›  Cristian

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

  •  0
  • Cristian  · 技术社区  · 7 年前

    所以我在做一些 promise 因为我需要一些同步运行的代码。在我有两个孩子之前一切都好 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

    未定义 因为在角度上是异步的,但在相同的 安慰日志 我可以看到数组存在,但如果我尝试访问它,它就会存在 未定义 . 帮助

    解决方案

    使用@trincot的代码,我减少了 then 我只用了三个代码。谢谢大家!

    1 回复  |  直到 4 年前
        1
  •  0
  •   trincot Jakube    7 年前

    您声明使用承诺链是因为希望同步运行代码,但这是不可能的。承诺链的各个部分是异步执行的。函数中的最后一行在任何 then

    此外,您不能期望函数调用返回电子邮件。目前,您的函数没有返回任何内容,因此当您调用该函数时,您将得到 undefined .

    但是,即使你想归还一些东西,也永远不会有结果。你最多可以回报一个承诺。

    您需要接受异步行为,并继续使用该模式。所以不要期望同步赋值。相反,继续使用 然后 .

    例如,您可以从一个立即解析的承诺开始,该承诺将空的结果对象传递给链:

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