Javascript node async/await不适用于我(当使用Postgres/node时-在转到下一个调用之前使用数据库更新)
Javascript node async/await不适用于我(当使用Postgres/node时-在转到下一个调用之前使用数据库更新),javascript,node.js,async-await,node-postgres,Javascript,Node.js,Async Await,Node Postgres,await在代码块更新db(使用postgres/node)时,未按预期进行阻塞。 我有一个异步函数调用的列表,每个调用都会创建一个数据库,随后的每个调用都会处理由上一个调用更新的数据 一行大约有八个调用,每个调用都必须更新正在处理的完整数据集,100%完成,然后再转到下一个 我试图使一切都不异步,但似乎由于我使用的库(postgres/node),我被迫使一切都异步/等待 在进行下一个函数调用之前,每个函数调用必须100%完成,因为下一步对字段不为null的行(上一步填充值的行)进行选择
await
在代码块更新db(使用postgres/node)时,未按预期进行阻塞。
我有一个异步函数调用的列表,每个调用都会创建一个数据库,随后的每个调用都会处理由上一个调用更新的数据
一行大约有八个调用,每个调用都必须更新正在处理的完整数据集,100%完成,然后再转到下一个
我试图使一切都不异步,但似乎由于我使用的库(postgres/node),我被迫使一切都异步/等待
在进行下一个函数调用之前,每个函数调用必须100%完成,因为下一步对字段不为null的行(上一步填充值的行)进行选择 我在每次通话前都有一个wait,它会做一些事情(参见下面的代码):
wait
,并完成其代码块
如果我注释掉后几行中的某些行(取决于前几行),并让程序运行到完成,则数据库将得到更新
代码在功能上没有问题,一切都正常,只是从开始到完成都不正常
在开始运行两个函数调用后,让它运行,然后我可以注释掉这些行,取消对流中后面的行的注释,然后再次运行,所有操作都按预期进行,但我无法在两个未注释的行都未注释的情况下运行到完成
在进入下一步之前,如何确保每个函数调用都100%完成,数据库中的所有更新都已完成
async/await对我不起作用
这不是伪代码,而是实际代码,正在执行,我正在使用,只更改了函数名。这是真正的工作代码,直接从我的IDE剪切粘贴。
// these are functions I call below (each in their own .js)
const insert_rows_to_db_from_csv = require('./insert_rows_to_db_from_csv')
const call_api_using_rows_from_function_above = require('./call_api_using_rows_from_function_above')
const and_so_on = require('./and_so_on')
const and_so_on_and_on = require('./and_so_on_and_on')
const and_so_on_and_on_and_on = require('./and_so_on_and_on_and_on')
// each of the above exports a main() function where I can call func.main() just // like this one defined below (this is my main() entry point)
module.exports = {
main: async function (csvFilePath) {
console.log('service: upload.main()')
try {
const csvList = []
let rstream = fs.createReadStream(csvFilePath)
.pipe(csv())
.on('data', (data) => csvList.push(data))
.on('end', async () => {
let num_rows = csvList.length
//step one (if I run these two, with step two calls below commented out, this works)
await insert_rows_to_db_from_csv.main(csvList);
await call_api_using_rows_from_function_above.main();
// step two
// blows up here, on the next function call,
// no rows selected in sql statements, must comment out, let the above run to
// completion, then comment out the rows above, and let these run separate
await work_with_rows_updated_in_previous_call_above.main(); // sets
await and_so_on.main();
await and_so_on_and_on.main();
await and_so_on_and_on_and_on.main();
})
} catch (err) {
console.log(err.stack)
} finally {
}
}
};
下面是我用来调用DB的插入/更新的一行代码:
return await pool.query(sql, values);
就这样,没别的了。这是通过使用:
npm安装页面
第2部分-继续, 我想问题可能就在这里。这就是我正在做的每一件事 API调用,然后插入(下一个函数调用依赖于此),这里有些代码的味道我无法分辨 调用processBatch(batch),调用API,获取响应,然后在其中调用`handleResponseDetail(response),插入发生在这里。我想问题就在这里,如果有什么想法的话 这是内部的一个代码块:
wait call_api_使用上面的函数_中的_行_调用.main()代码>
它会在没有错误的情况下完成,插入行并提交,然后调用下一个函数,而下一个函数找不到行(在此处插入)。但是整个main().js上的wait会阻塞并等待,所以我不明白
/**
* API call, and within call handleResponse which does the DB insert.
* @param batch
* @returns {Promise<*>}
*/
async function processBatch(batch) {
console.log('Processing batch');
return await client.send(batch).then(res => {
return handleResponseDetail(res);
}).catch(err => handleError(err));
}
// should this be async?
function handleResponseDetail(response) {
response.lookups.forEach(async function (lookup) {
if (typeof lookup.result[0] == "undefined") { // result[0] is Candidate #0
++lookup_fail;
console.log('No response from API for this address.')
} else {
++lookup_success;
const id = await insert(lookup);
}
});
}
/**
*API调用,并在调用handleResponse中插入DB。
*@param批处理
*@returns{Promise}
*/
异步函数processBatch(批处理){
console.log(“处理批”);
返回等待客户端。发送(批处理)。然后(res=>{
返回手柄响应详细信息(res);
}).catch(err=>handleError(err));
}
//这应该是异步的吗?
函数句柄响应详细信息(响应){
response.lookups.forEach(异步函数(查找){
如果(typeof lookup.result[0]=“undefined”){//result[0]是候选#0
++查找失败;
console.log('此地址没有API响应')
}否则{
++成功与否;
const id=等待插入(查找);
}
});
}
您的主功能当前所做的只是创建流、分配侦听器并立即返回。它不会像你试图让它做的那样等待所有的听众去解决
您需要将文件读取逻辑提取到另一个函数,该函数将返回仅在读取整个文件时才会解析的承诺,然后在main
function getCsvList(csvFilePath) {
return new Promise((resolve, reject) => {
const csvList = []
fs.createReadStream(csvFilePath)
.pipe(csv())
.on('data', (data) => csvList.push(data))
.on('end', () => {
resolve(csvList)
})
.on('error', (e) => reject(e))
})
}
module.exports = {
main: async function (csvFilePath) {
try {
const csvList = await getCsvList(csvFilePath)
await insert_rows_to_db_from_csv.main(csvList);
await call_api_using_rows_from_function_above.main();
await work_with_rows_updated_in_previous_call_above.main();
await and_so_on.main();
await and_so_on_and_on.main();
await and_so_on_and_on_and_on.main();
} catch (err) {
console.log(err.stack)
} finally {
}
}
};
考虑到第2部分编辑中的代码块,问题现在很清楚了:所有insert()的
都被安排在async/await
代码其余部分的阻塞上下文之外!这是因为。有关详细信息,请参阅forEach
我已经对您现有的代码进行了注释,以显示问题:
function handleResponseDetail(response) { //synchronous function
response.lookups.forEach(async function (lookup) { //asynchronous function
//these async functions all get scheduled simultaneously
//without waiting for the previous one to complete - that's why you can't use forEach like this
if (typeof lookup.result[0] == "undefined") { // result[0] is Candidate #0
++lookup_fail;
console.log('No response from API for this address.')
} else {
++lookup_success;
const id = await insert(lookup); //this ONLY blocks the inner async function, not the outer `handleResponseDetail`
}
});
}
下面是该函数的一个固定版本,它应该可以像您期望的那样工作:
async function handleResponseDetail(response) {
for(const lookup of response.lookups) {
if (typeof lookup.result[0] == "undefined") { // result[0] is Candidate #0
++lookup_fail;
console.log('No response from API for this address.')
} else {
++lookup_success;
const id = await insert(lookup); //blocks handleResponseDetail until done
}
}
}
或者,如果插入顺序无关紧要,您可以使用Promise.all
提高效率:
async function handleResponseDetail(response) {
await Promise.all(response.lookups.map(async lookup => {
if (typeof lookup.result[0] == "undefined") { // result[0] is Candidate #0
++lookup_fail;
console.log('No response from API for this address.')
} else {
++lookup_success;
const id = await insert(lookup);
}
})); //waits until all insertions have completed before returning
}
重申一下,您不能轻松地将.forEach()
与async/await一起使用,因为.forEach()
只是同步调用数组中每个元素的给定函数,而不考虑在调用下一个承诺之前等待每个承诺。如果您需要循环在每个元素之间阻塞,或者在从函数返回之前等待所有元素完成处理(这是您的用例),则需要使用不同的for循环,或者如上所述使用Promise.all()
。什么是cvsList
?请显示实际和真实的数据库调用,不是你的伪代码。如果您向我们展示实际的和真实的代码,我们只能将您所做的与实际的数据库API进行比较。您必须正确地使用等待
,它才能执行您想要的操作,如果没有看到真正的代码,我们无法看到您是否正确地使用它。我不知道w