【问题标题】:Getting undefined because of asynchronous calling由于异步调用而变得未定义
【发布时间】:2014-05-26 00:21:51
【问题描述】:

我在这里遇到了一些问题。我正在为 Sencha Touch 应用程序开发 NodeJS 的后端,并且在某些时候我正在调用一个函数,但在获取该函数返回语句之前,我将进入下一行代码。

这是我的代码...

.... for loop ....
        if(resultSet[k].id_bus == busDocs[n].id_bus && resultSet[k].id_bus_variation == busDocs[n].id_bus_variation){
            resultSet[k].s_origin_description = busDocs[n].s_origin_description;
            resultSet[k].s_eta = vehicle != null ? getVehicleETA(db, vehicle) : 'Unknown';
            console.log('after getting eta');
            resultSet[k].s_destination_description = busDocs[n].s_destination_description;
        }
    }
}
res.send(JSON.stringify(resultSet));
....

这是我的 getVehicleETA 函数...

getVehicleETA = function(db, vehicle){
    var position = vehicle.position;

    function compare(a,b) {
      if (a.n_stop_number < b.n_stop_number)
         return -1;
      if (a.n_stop_number > b.n_stop_number)
        return 1;
      return 0;
    }

    db.get('busstops').find({$query:{$and:[{id_bus: vehicle.id_bus}, {id_bus_variation: vehicle.id_bus_variation}]},$orderBy:{n_stop_number: 1}},function(e, docs){
        var distance = 0;
        if(docs.length != 0){
            docs.sort(compare);
            var nextBusStop = null;
            for(var i=0; i<docs.length; i++){
                if(i+1 < docs.length){
                    var routeSegmentLength = Math.sqrt(Math.pow(docs[i +1].coord_x - docs[i].coord_x, 2) + Math.pow(docs[i +1].coord_y - docs[i].coord_y, 2));
                    var firstStopDistance = Math.sqrt(Math.pow(vehicle.coord_x - docs[i].coord_x, 2) + Math.pow(vehicle.coord_y - docs[i].coord_y, 2));
                    var secondStopDistance = Math.sqrt(Math.pow(vehicle.coord_x - docs[i +1].coord_x, 2) + Math.pow(vehicle.coord_y - docs[i +1].coord_y, 2));
                    if(nextBusStop != null){
                        distance += routeSegmentLength;
                    }

                    if(secondStopDistance < routeSegmentLength && firstStopDistance < routeSegmentLength){    
                        nextBusStop = docs[i+1];
                    }
                }
            }
            console.log(((distance/(1000 * vehicle.speed)) * 60))
            return ((distance/(1000 * vehicle.speed)) * 60);
        }
    });
}

如果这工作正常,我将不得不先查看getVehicleETAconsole.log,然后再查看console.log('after getting eta');,但我却反其道而行之。我知道这实际上是正确的行为,因为它没有阻塞线程并继续在代码中运行,但这对我不起作用,因为我什至在获得 getVehicleETA 结果之前就发送了 resultSet,我需要resultSet 的项目在发送之前设置为 s_eta 属性。

这样做的正确方法是什么?

【问题讨论】:

    标签: node.js asynchronous callback return synchronous


    【解决方案1】:

    正确的方法是在 getVehicleETA 函数中进行回调。

    让我给你看一个插图:

    getVehicleETA = function(db,vehicle,callback){
        /*do some stuff*/
        //return the result in callback.
        callback(result); 
    }
    
    resultSet[k].s_origin_description = busDocs[n].s_origin_description;
    if(vehicle!=null){
        getVehicleETA(db,vehicle,function(result){
            resultSet[k].s_eta = result;            
            nextAction()
        });
    }else{
        resultSet[k].s_eta = "unknown";
        nextAction();
    }
    
    function nextAction (){
        console.log('after getting eta');
        resultSet[k].s_destination_description = busDocs[n].s_destination_de
        res.send(JSON.stringify(resultSet));
    }
    

    希望这对你有用。

    【讨论】:

      【解决方案2】:

      您正在调用一个异步函数,就好像它是同步的一样。此外,从异步函数的回调中返回值是没有意义的。您必须将回调传递给函数,然后在数据库回调中使用数据库中的值调用该回调。

      您应该考虑使用async 模块来帮助您处理循环中的异步函数调用。

      【讨论】:

      • 不赞成异步吗?
      • @lascort 不,它实际上是一个相当流行的模块,用于很多项目(包括 npm 之外)。不过,它目前在npm 上有 1000 名家属。
      猜你喜欢
      • 1970-01-01
      • 2018-08-12
      • 1970-01-01
      • 2020-11-19
      • 2021-12-21
      • 1970-01-01
      • 2016-04-03
      • 2017-10-05
      • 2018-05-20
      相关资源
      最近更新 更多