所有问题都不能按正确的顺序解决

Q.all doesnt resolve in correct order

本文关键字:顺序 解决 有问题 不能按      更新时间:2023-09-26

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

代码应该做以下事情:

a)执行查询并使用得到的纬度/长度对

b)计算最短路径(使用异步函数)和

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

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

奇怪的是,当我在computeRoutes()中不循环坐标[],而只是为坐标[0]计算一条路由时,承诺链成功了(当然我只看到一条路由返回JSON)

你知道这里有什么问题吗?

谢谢! !

完整代码:

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

试错后找到了答案。

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

切换到带函数的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();
    });