try 块中抛出异常后,catch 块不会立即执行
Catch block does not execute immediately after exception is thrown in try block
我有一些 Javascript 代码,它的行为与我预期的不一样。谁能告诉我这是怎么回事?
这是一个简化版本:
let recordsProcessed = 0
await parser(fileBuffer,
// Process row
async (row: Record<string, any>) => {
recordsProcessed += 1
try {
console.log('Processing record', recordsProcessed)
await processRow(row)
} catch (e) {
console.log('Failure at record', recordsProcessed)
}
}
)
async parser(fileBuffer: Buffer, rowCb: Function, ...) : Promise<number> {
...
return new Promise((resolve, reject) => {
parseFile(fileBuffer, options)
.on('error', (error:any) => reject(error))
.on('data', async row => await rowCb(row))
.on('end', (count: any) => resolve(count))
})
...
}
这里的parser()是一个异步函数,但是它也调用了一些传递给它的回调函数(我这里只展示了一个,其实还有多个)。它为文件中的每一行调用 rowCb() 回调。
这是异步回调中的 try/catch 块,它的行为与我预期的不同。我正在使用一个包含三行的测试文件,这将导致对 processRow() 的每次调用都抛出异常。所以,我希望 console.logs 的输出是:
Processing record 1
Failure at record 1
Processing record 2
Failure at record 2
Processing record 3
Failure at record 3
但我得到的是:
Processing record 1
Processing record 2
Processing record 3
Failure at record 3
Failure at record 3
Failure at record 3
为什么会这样?由于我正在等待 processRow(),它不应该与 try/catch 块在同一范围内,因此 catch() 应该在 processRow() 抛出异常后立即处理吗?
您需要在解析器中添加一个新变量来获取当前记录的编号。您应该使用该变量而不是全局变量。
let recordsProcessed = 0
await parser(fileBuffer,
// Process row
async (row: Record<string, any>) => {
recordsProcessed += 1
let thisRecordNum = recordsProcessed;
try {
console.log('Processing record', thisRecordNum)
await processRow(row)
} catch (e) {
console.log('Failure at record', thisRecordNum)
}
}
)
如果它正在处理多行,parseFile()
内部一定有一些循环。目前还不清楚它是您的代码还是来自某个库,但该循环要么期望使用异步回调,要么不期望。也许那些未显示的 options
也影响了这一点。
如果它使用 await
的循环,输出将是您所期望的:
async function thrower(i) {
throw "throwing " + i;
}
let somevariable = 0;
async function wrapper(i) {
try {
somevariable++;
console.log("calling", i, "(" + somevariable + ")");
await thrower(i);
} catch (x) {
console.log("caught", x, "(" + somevariable + ")");
}
}
(async function() {
for await (let i of [1, 2, 3]) // <-- async-aware loop
wrapper(i);
})()
但是,如果它不使用 await
,那么当 wrapper()
遇到它自己的 await
行时,循环会立即进行:
async function thrower(i) {
throw "throwing " + i;
}
let somevariable = 0;
async function wrapper(i) {
try {
somevariable++;
console.log("calling", i, "(" + somevariable + ")");
await thrower(i);
} catch (x) {
console.log("caught", x, "(" + somevariable + ")");
}
}
(async function() {
for (let i of [1, 2, 3]) // <-- async-unaware loop
wrapper(i);
})()
而且如果是古代的forEach()
,那么即使尝试await
也无所谓await
:
async function thrower(i) {
throw "throwing " + i;
}
let somevariable = 0;
async function wrapper(i) {
try {
somevariable++;
console.log("calling", i, "(" + somevariable + ")");
await thrower(i);
} catch (x) {
console.log("caught", x, "(" + somevariable + ")");
}
}
(async function() {
//[1, 2, 3].forEach(wrapper); // <- would be enough to produce the same output
[1, 2, 3].forEach(async function(i){
await wrapper(i); // <- absolutely futile attempt to wait,
// forEach just can't work asynchronously
});
})()
我有一些 Javascript 代码,它的行为与我预期的不一样。谁能告诉我这是怎么回事?
这是一个简化版本:
let recordsProcessed = 0
await parser(fileBuffer,
// Process row
async (row: Record<string, any>) => {
recordsProcessed += 1
try {
console.log('Processing record', recordsProcessed)
await processRow(row)
} catch (e) {
console.log('Failure at record', recordsProcessed)
}
}
)
async parser(fileBuffer: Buffer, rowCb: Function, ...) : Promise<number> {
...
return new Promise((resolve, reject) => {
parseFile(fileBuffer, options)
.on('error', (error:any) => reject(error))
.on('data', async row => await rowCb(row))
.on('end', (count: any) => resolve(count))
})
...
}
这里的parser()是一个异步函数,但是它也调用了一些传递给它的回调函数(我这里只展示了一个,其实还有多个)。它为文件中的每一行调用 rowCb() 回调。
这是异步回调中的 try/catch 块,它的行为与我预期的不同。我正在使用一个包含三行的测试文件,这将导致对 processRow() 的每次调用都抛出异常。所以,我希望 console.logs 的输出是:
Processing record 1
Failure at record 1
Processing record 2
Failure at record 2
Processing record 3
Failure at record 3
但我得到的是:
Processing record 1
Processing record 2
Processing record 3
Failure at record 3
Failure at record 3
Failure at record 3
为什么会这样?由于我正在等待 processRow(),它不应该与 try/catch 块在同一范围内,因此 catch() 应该在 processRow() 抛出异常后立即处理吗?
您需要在解析器中添加一个新变量来获取当前记录的编号。您应该使用该变量而不是全局变量。
let recordsProcessed = 0
await parser(fileBuffer,
// Process row
async (row: Record<string, any>) => {
recordsProcessed += 1
let thisRecordNum = recordsProcessed;
try {
console.log('Processing record', thisRecordNum)
await processRow(row)
} catch (e) {
console.log('Failure at record', thisRecordNum)
}
}
)
如果它正在处理多行,parseFile()
内部一定有一些循环。目前还不清楚它是您的代码还是来自某个库,但该循环要么期望使用异步回调,要么不期望。也许那些未显示的 options
也影响了这一点。
如果它使用 await
的循环,输出将是您所期望的:
async function thrower(i) {
throw "throwing " + i;
}
let somevariable = 0;
async function wrapper(i) {
try {
somevariable++;
console.log("calling", i, "(" + somevariable + ")");
await thrower(i);
} catch (x) {
console.log("caught", x, "(" + somevariable + ")");
}
}
(async function() {
for await (let i of [1, 2, 3]) // <-- async-aware loop
wrapper(i);
})()
但是,如果它不使用 await
,那么当 wrapper()
遇到它自己的 await
行时,循环会立即进行:
async function thrower(i) {
throw "throwing " + i;
}
let somevariable = 0;
async function wrapper(i) {
try {
somevariable++;
console.log("calling", i, "(" + somevariable + ")");
await thrower(i);
} catch (x) {
console.log("caught", x, "(" + somevariable + ")");
}
}
(async function() {
for (let i of [1, 2, 3]) // <-- async-unaware loop
wrapper(i);
})()
而且如果是古代的forEach()
,那么即使尝试await
也无所谓await
:
async function thrower(i) {
throw "throwing " + i;
}
let somevariable = 0;
async function wrapper(i) {
try {
somevariable++;
console.log("calling", i, "(" + somevariable + ")");
await thrower(i);
} catch (x) {
console.log("caught", x, "(" + somevariable + ")");
}
}
(async function() {
//[1, 2, 3].forEach(wrapper); // <- would be enough to produce the same output
[1, 2, 3].forEach(async function(i){
await wrapper(i); // <- absolutely futile attempt to wait,
// forEach just can't work asynchronously
});
})()