我想从一个对象中的两个数据库查询返回结果。
function route(start, end) {
return new Promise((resolve, reject) => {
const queries = routeQuery(start, end);
var empty_obj = new Array();
for (i=0; i<queries.length; i++) {
query(queries[i], (err, res) => {
if (err) {
reject('query error', err);
console.log(err);
return;
} else {
empty_obj.push(res.rows);
}});
}
console.log(empty_obj);
resolve({coords: empty_obj});
});
}
这是我现在的代码,查询工作正常,但是由于某种原因,将每个结果放入一个空数组都无法正常工作。当我控制台记录该空对象时,它保持为空。目的是使用包含两个查询结果的生成的对象来解决promise。我正在使用node-postgres进行查询。
res的输出是一个对象:
{
command: 'SELECT',
rowCount: 18,
oid: null,
rows: [
{ ...
答案 0 :(得分:0)
我建议您将query
函数转换为Promise
,以便可以使用Promise.all
:
// turn the callback-style asynchronous function into a `Promise`
function queryAsPromise(arg) {
return new Promise((resolve, reject) => {
query(arg, (err, res) => {
if (err) {
console.error(err);
reject(err);
return;
}
resolve(res);
});
});
}
然后,您可以在route
函数中执行以下操作:
function route(start, end) {
const queries = routeQuery(start, end);
// use `Promise.all` to resolve with
// an array of results from queries
return Promise.all(
queries.map(query => queryAsPromise(query))
)
// use `Array.reduce` w/ destructing assignment
// to combine results from queries into a single array
.then(results => results.reduce(
(acc, item) => [...acc, ...item.rows],
[]
))
// return an object with the `coords` property
// that contains the final array
.then(coords => {
return { coords };
});
}
route(1, 10)
.then(result => {
// { coords: [...] }
})
.catch(error => {
// handle errors appropriately
console.error(error);
});
参考:
希望这会有所帮助。
答案 1 :(得分:0)
您当前面临的问题是由于以下事实造成的:
resolve({coords: empty_obj});
不在回调内。因此,承诺会在调用查询回调并将行推入empty_obj
之前解析。您可以通过以下方式将其移至query
回调中:
empty_obj.push(res.rows); // already present
if (empty_obj.length == queries.length) resolve({coords: empty_obj});
这将解决所有行被推送时的承诺,但又给您带来另一个问题。回调可能未按顺序调用。这意味着结果顺序可能与queries
顺序不匹配。
解决此问题的最简单方法是将每个单独的回调转换为Promise。然后使用Promise.all
等到所有承诺都解决。结果数组将具有相同顺序的数据。
function route(start, end)
const toPromise = queryText => new Promise((resolve, reject) => {
query(queryText, (error, response) => error ? reject(error) : resolve(response));
});
return Promise.all(routeQuery(start, end).map(toPromise))
.then(responses => ({coords: responses.map(response => response.rows)}))
.catch(error => {
console.error(error);
throw error;
});
}