![](/img/trans.png)
[英]Is there any problem in handling 'throw error' inside try-catch in async await?
[英]Error handling using try / catch inside async / await on firebase onCall cloud function
我目前正在将此云功能部署到我的Firebase应用程序中,并且将使用Node v8运行时,因此可以使用async / await语法。
我在处理同一功能中可能发生的各种错误时遇到了一些麻烦。
完成后,该函数应接收一个url参数以对该URL进行请求,并在响应主体中抓取一些数据并将其保存到数据库中。 此时,它只是返回与测试目的相同的URL字符串。
到目前为止,这就是我所拥有的:
const functions = require('firebase-functions');
const request = require('request');
const cheerio = require('cheerio');
exports.getDataFromUrl = functions.https.onCall((data) => {
// PROMISIFIED REQUEST TO USE WITH ASYNC AWAIT
const promisifiedRequest = function(options) {
return new Promise((resolve,reject) => {
request(options, (error, response, body) => {
if (error) {
return reject(error);
}
return resolve(response);
});
});
};
// CHECK IF URL IS PRESENT, IF NOT, THROW ERROR
if (!data.url) {
throw new functions.https.HttpsError('invalid-argument','The URL parameter was invalid.');
}
// URL passed from the client.
const url = data.url;
// IIFE ASYNC FUNCTION
(async function() {
// TRY BLOCK
try {
// REQUEST OPTIONS TO THE URL
const urlOptions = {
url: 'https://www.someINEXISTENT.url',
method: 'GET',
gzip: true,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36'
},
jar: true
};
// CREATE RESPONSE AND CHEERIO OBJECT
let response = null;
let $ = null;
// SEND REQUEST TO URL, AND PARSE WITH CHEERIO
response = await promisifiedRequest(urlOptions);
$ = cheerio.load(response.body);
} // TRY BLOCK - END
// CATCH BLOCK
catch (error) {
console.log('Caught an error: ' + error);
throw new functions.https.HttpsError('unknown', error.message, error);
}
console.log('End of async function...');
})()
return {
yourUrl : url
};
});
我的第一个错误案例是在URL无效时发生的,它工作正常。 当我抛出以下错误时,执行停止:
throw new functions.https.HttpsError('invalid-argument','URL invalid.');
据我了解,有必要抛出此HttpsError
以便能够赶上客户端。 而且有效。 发生这种情况时,我会在客户端收到此错误。
我的问题是第二种类型的错误,应该由async函数中的try / catch语句捕获 。 例如,当我尝试请求不存在的网址时,就会发生该错误。
这是怎么回事(下图):
catch块已激活,我可以在功能控制台上看到`console.log(),但是不知何故它不会引发错误,并且即使“我没有抛出catch块也将其扔到异步函数中”从捕获块里面钻研 我的客户端代码根本没有收到此错误。 从我的客户的角度来看,该功能完整无误。
错误:
错误:(节点:5160)UnhandledPromiseRejectionWarning:未处理的承诺拒绝。 该错误是由于在没有catch块的情况下抛出异步函数而引起的,或者是由于拒绝了未经.catch()处理的诺言而引起的。 (拒绝ID:1)
我尝试添加和外部try/catch
块。 并且在异步IIFE之后也使用.catch()
将错误抛出到异步函数之外,但是并不能解决问题。
我究竟做错了什么?
...但是以某种方式不会引发错误...
那是因为没有东西使用async
函数创建的promise,而throw
被拒绝。 承诺的规则之一是:您必须处理承诺被拒绝或将结果返回给其他将要发生的事情。
functions.https.onCall
允许您返回promise ,所以我将回调设为async
函数,而不是使用异步IIFE。 您无法同步提供结果或引发错误,因为您正在处理异步操作。
这些方面的内容(可能需要调整,请参阅***
注释):
const functions = require('firebase-functions');
const request = require('request');
const cheerio = require('cheerio');
// *** No reason to define this within `onCall`'s handler
const promisifiedRequest = function(options) {
return new Promise((resolve,reject) => {
request(options, (error, response, body) => {
if (error) {
return reject(error);
}
return resolve(response);
});
});
};
exports.getDataFromUrl = functions.https.onCall(async (data) => { // *** Make it async, since `onCall` allows you to return a promise
// CHECK IF URL IS PRESENT, IF NOT, THROW ERROR
if (!data.url) {
throw new functions.https.HttpsError('invalid-argument','The URL parameter was invalid.');
}
// URL passed from the client.
const url = data.url;
// *** No need for try/catch unless you want to change the error
// *** If you do, though, add it back and use `throw` in the `catch` block (as you did originally).
// *** That will make the promise this async function returns reject.
// REQUEST OPTIONS TO THE URL
const urlOptions = {
url: 'https://www.someINEXISTENT.url',
method: 'GET',
gzip: true,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36'
},
jar: true
};
// CREATE RESPONSE AND CHEERIO OBJECT
let response = null;
let $ = null;
// SEND REQUEST TO URL, AND PARSE WITH CHEERIO
response = await promisifiedRequest(urlOptions);
$ = cheerio.load(response.body);
// *** Do you really want to return the URL? Not something from the body of what you requested?
return {
yourUrl : url
};
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.