将回调函数的结果推入数组时如何等待迭代完成
How to wait for the iteration to finish when pushing result of a callback function into an array
实现 array.push 以便在 forEach 迭代完成后返回 "array_of_results" 的正确方法是什么?
const postgres = require("./postgres");
function get_array(value) {
var array_of_results = []
value.forEach( item => {
postgres.query(item["id"],function(res){
console.log(res) //gives proper res after empty array
array_of_results.push(res);
})
});
console.log(array_of_results)// prints empty array
return array_of_results;
}
编辑:
postgres.js 看起来像:
const { Pool } = require("pg");
const pool = new Pool();
var query_string = "select...."
function query(id, call) {
pool.query(query_string, [id], (err, res) => {
if (err) {
console.log(err.stack)
} else {
call(res.rows[0])
}
})
}
module.exports = {
query
}
有几种方法可以做到这一点,但首先您需要了解实际发生的事情。
在 postgres.query(item["id"],function(res){
中,您使用 (1) 项目 ID 和 (2) 回调函数调用 postgres.query。该调用发生,然后立即在您的调用代码中继续。所以现在你刚刚向你的数据库发送了一堆请求,然后立即 return 一个空数组。这些回调 (2) 尚未被调用。
要将数据返回给调用函数,您需要传递回调而不是使用 return
,或者更改为 async/await。
在循环的每次迭代中使用 async/await 效率不高,因为您要依次等待对 return 的每次调用。对于最有效的方法,您需要触发请求并等待它们全部完成。您可以使用 promises 来做到这一点。
您可以修改代码,为循环的每次迭代将承诺推送到数组中,然后在承诺数组上调用(并等待)Promise.all
。
这是为您重写的基本内容:
postgres.js:
function query(id) {
return new Promise((resolve, reject) => {
pool.query(query_string, [id], (err, res) => {
if (err) {
console.log(err.stack)
reject(err)
} else {
resolve(res.rows[0])
}
})
})
}
module.exports = {
query
}
get_array 实施:
async function get_array(value) {
var array_of_promises = [], array_of_results = []
value.forEach( item => {
array_of_promises.push(postgres.query(item["id"]));
});
array_of_results = await Promise.all(array_of_promises);
console.log(array_of_results)// prints populated array
return array_of_results;
}
请注意,当您调用 get_array
时,您必须在调用之前使用 await,例如将 var array = get_array(items)
更改为 var array = await get_array(items)
并在函数中使用 await
需要将其声明为异步函数。
如果不能声明为异步函数,可以修改调用代码来消费promise:
var arrayPromise = get_array(items);
arrayPromise.then((results) => {
// do something with results
// but remember you cannot _return_ from within a callback, as discussed above
});
实现 array.push 以便在 forEach 迭代完成后返回 "array_of_results" 的正确方法是什么?
const postgres = require("./postgres");
function get_array(value) {
var array_of_results = []
value.forEach( item => {
postgres.query(item["id"],function(res){
console.log(res) //gives proper res after empty array
array_of_results.push(res);
})
});
console.log(array_of_results)// prints empty array
return array_of_results;
}
编辑: postgres.js 看起来像:
const { Pool } = require("pg");
const pool = new Pool();
var query_string = "select...."
function query(id, call) {
pool.query(query_string, [id], (err, res) => {
if (err) {
console.log(err.stack)
} else {
call(res.rows[0])
}
})
}
module.exports = {
query
}
有几种方法可以做到这一点,但首先您需要了解实际发生的事情。
在 postgres.query(item["id"],function(res){
中,您使用 (1) 项目 ID 和 (2) 回调函数调用 postgres.query。该调用发生,然后立即在您的调用代码中继续。所以现在你刚刚向你的数据库发送了一堆请求,然后立即 return 一个空数组。这些回调 (2) 尚未被调用。
要将数据返回给调用函数,您需要传递回调而不是使用 return
,或者更改为 async/await。
在循环的每次迭代中使用 async/await 效率不高,因为您要依次等待对 return 的每次调用。对于最有效的方法,您需要触发请求并等待它们全部完成。您可以使用 promises 来做到这一点。
您可以修改代码,为循环的每次迭代将承诺推送到数组中,然后在承诺数组上调用(并等待)Promise.all
。
这是为您重写的基本内容:
postgres.js:
function query(id) {
return new Promise((resolve, reject) => {
pool.query(query_string, [id], (err, res) => {
if (err) {
console.log(err.stack)
reject(err)
} else {
resolve(res.rows[0])
}
})
})
}
module.exports = {
query
}
get_array 实施:
async function get_array(value) {
var array_of_promises = [], array_of_results = []
value.forEach( item => {
array_of_promises.push(postgres.query(item["id"]));
});
array_of_results = await Promise.all(array_of_promises);
console.log(array_of_results)// prints populated array
return array_of_results;
}
请注意,当您调用 get_array
时,您必须在调用之前使用 await,例如将 var array = get_array(items)
更改为 var array = await get_array(items)
并在函数中使用 await
需要将其声明为异步函数。
如果不能声明为异步函数,可以修改调用代码来消费promise:
var arrayPromise = get_array(items);
arrayPromise.then((results) => {
// do something with results
// but remember you cannot _return_ from within a callback, as discussed above
});