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