Q.all没有以正确的顺序解决

时间:2014-07-10 11:41:05

标签: javascript node.js q

我在Node.js中遇到Q承诺的执行顺序有问题。

代码应该执行以下操作:

a)执行查询并使用生成的lat / lon对

b)计算最短路径(使用异步功能)和

c)归还他们

  query() // Runs the query
    .then(function() {
      return computeRoutes(); // Calculates the routes
    })
    .then(function() {
      return returnRoutes(); // Returns the routes as JSON
    });

问题是,虽然coordinates []数组在query()中填充并在computeRoutes()中填充/可用,但routes []数组在returnRoutes()中保持为空。

奇怪的是,当我不在computeRoutes()中循环遍历coordinates []而只是为坐标[0]计算一条路线时,承诺链成功(但是当然我看到只有一条路由作为JSON返回)< / p>

关于这里可能出现什么问题的任何想法?

谢谢!

完整代码:

app.get('/',
function(req, res) {

  var id = parseInt(req.query.id);
  var radius = parseInt(req.query.radius) || 5000;
  var routes = [];
  var coordinates = [];

  function query() {
    var deferred = Q.defer();

    console.log('Starting query function...');
    var query = client.query('SELECT ST_X(ST_Transform(ST_SetSRID(a.geom, 3857),4326)) AS fromlat, ST_Y(ST_Transform(ST_SetSRID(a.geom, 3857),4326)) AS fromlon, ST_X(ST_Transform(ST_SetSRID(b.geom, 3857),4326)) AS tolat, ST_Y(ST_Transform(ST_SetSRID(b.geom, 3857),4326)) AS tolon FROM emme_veh AS c, emme_nodes3857 AS b, emme_nodes3857 AS a WHERE c.fid = a.id AND c.tid = b.id AND c.fid = $1 AND ST_Distance(a.geom, b.geom) < $2', [id, radius], function(err, result) {
      console.log('Inside query. result.rows.length:',result.rows.length);

      for(var i in result.rows) {
        coordinates.push({'from':[result.rows[i].fromlon,result.rows[i].fromlat], 'to':[result.rows[i].tolon,result.rows[i].tolat]});
      }

      deferred.resolve();
    });
    return deferred.promise;
  }

  function computeRoutes() {
    var the_promises = [];

    for(var i in coordinates) {
      var deferred = Q.defer();

      var query = {coordinates: [coordinates[i].from, coordinates[i].to], alternateRoute: false}
      osrm.route(query, function(err, result) {
        if(err) return res.json({"error": err.message});
        // console.log(result.route_geometry);
        routes.push(result.route_geometry);
        deferred.resolve();
      });
      the_promises.push(deferred.promise);
    }
    return Q.all(the_promises);
  }

  function returnRoutes() {
    return res.json(routes);
  }

  query()
    .then(function() {
      return computeRoutes();
    })
    .then(function() {
      return returnRoutes();
    });

});

1 个答案:

答案 0 :(得分:2)

在一些试验错误后找到了答案。

问题是我使用for..in循环在computeRoutes()函数中生成promise。

使用函数切换到forEach循环就可以了。

工作代码段(查看computeRoutes()部分):

app.get('/',
function(req, res) {

  var id = parseInt(req.query.id);
  var radius = parseInt(req.query.radius) || 5000;
  var routes = [];
  var coordinates = [];

  function query() {
    var deferred = Q.defer();

    console.log('Starting query function...');
    var query = client.query('SELECT ST_X(ST_Transform(ST_SetSRID(a.geom, 3857),4326)) AS fromlat, ST_Y(ST_Transform(ST_SetSRID(a.geom, 3857),4326)) AS fromlon, ST_X(ST_Transform(ST_SetSRID(b.geom, 3857),4326)) AS tolat, ST_Y(ST_Transform(ST_SetSRID(b.geom, 3857),4326)) AS tolon FROM emme_veh AS c, emme_nodes3857 AS b, emme_nodes3857 AS a WHERE c.fid = a.id AND c.tid = b.id AND c.fid = $1 AND ST_Distance(a.geom, b.geom) < $2', [id, radius], function(err, result) {
      console.log('Inside query. result.rows.length:',result.rows.length);

      for(var i in result.rows) {
        coordinates.push({'from':[result.rows[i].fromlon,result.rows[i].fromlat], 'to':[result.rows[i].tolon,result.rows[i].tolat]});
      }

      deferred.resolve();
    });
    return deferred.promise;
  }

  function computeRoutes() {
    var the_promises = [];

    console.log('Inside computeRoutes()');

    coordinates.forEach(function(coordinate) {
      var deferred = Q.defer();

      osrm.route({coordinates: [coordinate.from, coordinate.to], alternateRoute: false}, function(err, result) {      
        deferred.resolve(result);
        routes.push(result.route_geometry);
      });
      the_promises.push(deferred.promise);
    });

    return Q.all(the_promises);
  }

  function returnRoutes() {
    console.log('Inside returnRoutes()');
    return res.json(routes);
  }

  query()
    .then(function() {
      console.log('then() 1');
      return computeRoutes();
    })
    .then(function() {
      console.log('then() 2');
      return returnRoutes();
    });