NodeJS - 正确捕获异步函数的错误
NodeJS - Properly catch errors of async functions
我正在编写一个脚本,通过 API 从 Google 云指标中提取数据,这时我无意中发现我不知道如何正确捕获异步函数的错误。 :O
这是来自 google 云的示例代码:
// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');
// Creates a client
const client = new monitoring.MetricServiceClient();
/**
* TODO(developer): Uncomment and edit the following lines of code.
*/
const projectId = 'XXXXXXXXX';
async function getMetrics() {
const request = {
name: client.projectPath(projectId),
filter: 'metric.type="cloudsql.googleapis.com/database/cpu/utilization"',
interval: {
startTime: {
// Limit results to the last 20 minutes
seconds: Date.now() / 1000 - 60 * 1,
},
endTime: {
seconds: Date.now() / 1000,
},
},
// Don't return time series data, instead just return information about
// the metrics that match the filter
view: 'HEADERS',
};
// Writes time series data
console.log('start')
const [timeSeries] = await client.listTimeSeries(request);
console.log('Found data points for the following instances:');
timeSeries.forEach(data => {
console.log(data.metric.labels.instance_name);
});
}
getMetrics();
函数listTimeSeries
returns一个承诺。我收到一条错误消息,提示我需要经过身份验证才能执行该操作,没问题。
问题是我无法捕获该错误。
我尝试用 try {...} catch (err) {...}
块围绕调用,但没有被捕获。
我试着像这样抓住它 const [timeSeries] = await client.listTimeSeries(request).catch(console.log);
- 运气不好。
我一定是遗漏了什么,因为我是 nodeJS 的新手,不支持从异步函数捕获错误。
我正在使用 nodeJS v14。
我想念什么?
提前致谢!
编辑
按照@CherryDT 的要求,这里是完整的错误输出:
希望不要太模糊。
编辑
事实证明,我一直试图捕捉错误的方式是好的。
问题的发生是因为 listTimeSeries
函数(来自外部库)引发了一个错误而不是拒绝承诺,这是不可能捕捉到的。
谢谢大家。
你可以做到。
(async function() {
try {
await getMetrics();
} catch(error) {
console.log("Error occured:", error);
}
})();
请注意,如果您试图捕获 Promise
中的错误,您可以使用 .then(() => { }).catch(err => { })
样式,但对于 async/await
您将需要 try { } catch(err) { }
样式来捕获错误。
编辑
通过这样做,如果承诺被拒绝,它必须捕获任何错误。如果您仍然无法捕捉到错误,这意味着您正在使用的库没有正确 reject
承诺 (Promise.reject()
),而是在承诺中进行了硬编码 throw error
而不是拒绝一个。对于这种情况,您不能对错误捕获做任何事情。
请注意,我指的是“异步函数”和“异步函数”。在 Javascript 中,“异步函数”表示 function created with the async keyword,而当我说“异步函数”时,我指的是传统意义上的任何异步运行的函数。在 Javascript 中,使用 async 关键字创建的函数实际上只是底层的承诺。
如果异步函数(在 promises 内)抛出的错误可以被捕获,您的代码 将 工作。不幸的是,they can't. Unless the function is using the async function
syntax, errors in promises must be wrapped with reject
. See the MDN example 我们在这里看到的陷阱:
// Throwing an error will call the catch method most of the time
var p1 = new Promise(function(resolve, reject) {
throw new Error('Uh-oh!');
});
p1.catch(function(e) {
console.error(e); // "Uh-oh!"
});
// Errors thrown inside asynchronous functions will act like uncaught errors
var p2 = new Promise(function(resolve, reject) {
setTimeout(function() {
throw new Error('Uncaught Exception!');
}, 1000);
});
p2.catch(function(e) {
console.error(e); // This is never called
});
// Errors thrown after resolve is called will be silenced
var p3 = new Promise(function(resolve, reject) {
resolve();
throw new Error('Silenced Exception!');
});
p3.catch(function(e) {
console.error(e); // This is never called
});
我相信 this is the code 在下面的库中抛出错误。请注意,另一个错误正在被正确 reject
ed。所有评论都是我的。
for (const methodName of metricServiceStubMethods) {
const callPromise = this.metricServiceStub.then(
stub => (...args: Array<{}>) => {
if (this._terminated) {
// This is the right thing to do!
return Promise.reject('The client has already been closed.');
}
const func = stub[methodName];
return func.apply(stub, args);
},
(err: Error | null | undefined) => () => {
// If this was an async function (as in, using the keyword async,
// not just literally an asynchronous function), this would work,
// because the async keyword is just syntactic sugar for creating
// a promise. But it's not so it can't be caught!
throw err;
}
);
我相信,在这种情况下,不幸的是您无法捕获此错误。
我正在编写一个脚本,通过 API 从 Google 云指标中提取数据,这时我无意中发现我不知道如何正确捕获异步函数的错误。 :O
这是来自 google 云的示例代码:
// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');
// Creates a client
const client = new monitoring.MetricServiceClient();
/**
* TODO(developer): Uncomment and edit the following lines of code.
*/
const projectId = 'XXXXXXXXX';
async function getMetrics() {
const request = {
name: client.projectPath(projectId),
filter: 'metric.type="cloudsql.googleapis.com/database/cpu/utilization"',
interval: {
startTime: {
// Limit results to the last 20 minutes
seconds: Date.now() / 1000 - 60 * 1,
},
endTime: {
seconds: Date.now() / 1000,
},
},
// Don't return time series data, instead just return information about
// the metrics that match the filter
view: 'HEADERS',
};
// Writes time series data
console.log('start')
const [timeSeries] = await client.listTimeSeries(request);
console.log('Found data points for the following instances:');
timeSeries.forEach(data => {
console.log(data.metric.labels.instance_name);
});
}
getMetrics();
函数listTimeSeries
returns一个承诺。我收到一条错误消息,提示我需要经过身份验证才能执行该操作,没问题。
问题是我无法捕获该错误。
我尝试用 try {...} catch (err) {...}
块围绕调用,但没有被捕获。
我试着像这样抓住它 const [timeSeries] = await client.listTimeSeries(request).catch(console.log);
- 运气不好。
我一定是遗漏了什么,因为我是 nodeJS 的新手,不支持从异步函数捕获错误。
我正在使用 nodeJS v14。
我想念什么?
提前致谢!
编辑
按照@CherryDT 的要求,这里是完整的错误输出:
希望不要太模糊。
编辑
事实证明,我一直试图捕捉错误的方式是好的。
问题的发生是因为 listTimeSeries
函数(来自外部库)引发了一个错误而不是拒绝承诺,这是不可能捕捉到的。
谢谢大家。
你可以做到。
(async function() {
try {
await getMetrics();
} catch(error) {
console.log("Error occured:", error);
}
})();
请注意,如果您试图捕获 Promise
中的错误,您可以使用 .then(() => { }).catch(err => { })
样式,但对于 async/await
您将需要 try { } catch(err) { }
样式来捕获错误。
编辑
通过这样做,如果承诺被拒绝,它必须捕获任何错误。如果您仍然无法捕捉到错误,这意味着您正在使用的库没有正确 reject
承诺 (Promise.reject()
),而是在承诺中进行了硬编码 throw error
而不是拒绝一个。对于这种情况,您不能对错误捕获做任何事情。
请注意,我指的是“异步函数”和“异步函数”。在 Javascript 中,“异步函数”表示 function created with the async keyword,而当我说“异步函数”时,我指的是传统意义上的任何异步运行的函数。在 Javascript 中,使用 async 关键字创建的函数实际上只是底层的承诺。
如果异步函数(在 promises 内)抛出的错误可以被捕获,您的代码 将 工作。不幸的是,they can't. Unless the function is using the async function
syntax, errors in promises must be wrapped with reject
. See the MDN example 我们在这里看到的陷阱:
// Throwing an error will call the catch method most of the time
var p1 = new Promise(function(resolve, reject) {
throw new Error('Uh-oh!');
});
p1.catch(function(e) {
console.error(e); // "Uh-oh!"
});
// Errors thrown inside asynchronous functions will act like uncaught errors
var p2 = new Promise(function(resolve, reject) {
setTimeout(function() {
throw new Error('Uncaught Exception!');
}, 1000);
});
p2.catch(function(e) {
console.error(e); // This is never called
});
// Errors thrown after resolve is called will be silenced
var p3 = new Promise(function(resolve, reject) {
resolve();
throw new Error('Silenced Exception!');
});
p3.catch(function(e) {
console.error(e); // This is never called
});
我相信 this is the code 在下面的库中抛出错误。请注意,另一个错误正在被正确 reject
ed。所有评论都是我的。
for (const methodName of metricServiceStubMethods) {
const callPromise = this.metricServiceStub.then(
stub => (...args: Array<{}>) => {
if (this._terminated) {
// This is the right thing to do!
return Promise.reject('The client has already been closed.');
}
const func = stub[methodName];
return func.apply(stub, args);
},
(err: Error | null | undefined) => () => {
// If this was an async function (as in, using the keyword async,
// not just literally an asynchronous function), this would work,
// because the async keyword is just syntactic sugar for creating
// a promise. But it's not so it can't be caught!
throw err;
}
);
我相信,在这种情况下,不幸的是您无法捕获此错误。