我使用async / await ecma6标准而没有任何自定义库。
我现在还没有得到如何正确捕获和抛出错误。 我有多个异步/等待函数,如果发生严重错误,我想把错误抛到顶部和所有异步函数并停止执行函数。
我试图从异步/ await函数中抛出异常并在目标函数中捕获它但在node.js中出现错误:
this.basicAuthLogin= async function(user)
{
"use strict";
const login = new Login(this.host, this.url, user, user.pw);
//getSessionID throws error
this.sessionID = getSessionID(result.request.response);
}
(node:13964)UnhandledPromiseRejectionWarning:未处理的承诺 rejection(rejection id:1):错误:getSessionID响应未定义 (节点:13964)[DEP0018]弃用警告:未处理的承诺 拒绝拒绝。在未来,承诺拒绝 未处理将以非零退出终止Node.js进程 码。附带调试器。
所以我似乎不允许从异步函数中抛出异常,甚至在node.js中的promise的catch块中重新抛出它?
那么我该怎么做呢? 我是否应该在异步函数中捕获错误并在promise中返回错误并重新抛出异步函数?
this.basicAuthLogin= async function(user)
{
"use strict";
const login = new Login(this.host, this.url, user, user.pw);
try{
//getSessionID throws error
this.sessionID = getSessionID(result.request.response);
} catch(err) { return err;}
}
但这意味着在我的第一个异步函数的调用堆栈中,每个函数都需要异步,我必须等待承诺,即使我真的不需要它。
我希望有人可以启发我。
此致 Ruvi
编辑基本调用堆栈伪代码:
async startTest[arr]{
for (var i = 0; i < arr.length; i++)
{
try {
await runStep(arr[i];
} catch(err) {
console.log(err);
break;
}
}
}
async runStep(step)
{
try {
var userIsValid = await validateUser(step.user);
var req = buildRequest(step.request);
var result = await sendRequest(req);
var verify = verifyResult();
} catch(err){ throw err;}
}
async validateUser(user)
{
//make checks
//
var result = await this.authenticate(parameter).catch(err => {throw err});
userFound = true;
}
function authenticate(parameter) {
//can throw async function
basicAuthLogin(parameter).catch(err => {throw err};
}
function async basicAuthLogin(parameter()
{
try {
//can throw async function
var result = await request(parameter);
//can throw sync function
this.sessionID = getSessionID(response);
//can throw sync function
} catch(err) { throw err; }
}
答案 0 :(得分:15)
关于async
/ await
的一个好处是它们使try
/ catch
能够使用您的异步代码。
您的第一个basicAuthLogin
功能绝对正常(前提是getSessionID
是同步功能; 如果它不是,您就会丢失 [你现在已经说过了] )。代码使用 await
basicAuthLogin
必须处理它将抛出的可能性(通过处理错误或允许它传播到其负责处理它的调用者)。所以:
// In an `async` function
try {
await this.basicAuthLogin(/*...*/);
} catch (e) {
// Handle the fact something failed
}
或
// NOT in an `async` function:
this.basicAuthLogin(/*...*/)
.catch(e => { /* Handle the fact something failed */ });
如果使用它的代码执行这两件事之一(或者让错误传播到执行这两件事之一的代码),那么您将无法获得&#34;未处理的拒绝&#34;错误。
在回答我的评论,询问getSessionID
是否异步时,您写道:
不,它不是异步它是一个简单的函数,它抛出一个异常,我想在调用堆栈中捕获5或6层,但似乎我不允许这样做。
这是一个实际的例子这样做(在我的情况下,我已经basicAuthLogin
实际使用getSessionID
之前的异步,但它并不重要):
const getSessionID = () => {
throw new Error("Failed");
};
const somethingAsync = () => new Promise(resolve => {
setTimeout(resolve, 100);
});
const basicAuthLogin = async function(user)
{
"use strict";
await somethingAsync();
/*
const login = new Login(this.host, this.url, user, user.pw);
*/
//getSessionID throws error
getSessionID();
};
const wrapper1 = async () => {
await basicAuthLogin();
};
const wrapper2 = async () => {
await wrapper1();
};
const wrapper3 = async () => {
await wrapper2();
};
// Top-level caller
(async () => {
try {
await wrapper3();
} catch (e) {
console.log("Caught error: " + e.message);
}
})();
&#13;
规则与异常一样(因为理论上这些是例外):
处理它(例如,try
/ catch
),或让它传播给调用者(通常不做任何事情),
最高级别必须处理它
规则#2意味着当您从非async
代码转换为async
代码(通常位于堆栈顶部)时,您需要一个包装器。之一:
(async () => {
try {
await theFirstAsyncFunction();
await theNextAsyncFunction();
await aThirdAsyncFunction();
} catch (e) {
// handle the error
}
})();
或
(async () => {
await theFirstAsyncFunction();
await theNextAsyncFunction();
await aThirdAsyncFunction();
})().catch(e => { /* handle the error */});
或当然:
theFirstAsyncFunction()
.then(() => theNextAsyncFunction())
.then(() => aThirdAsyncFunction())
.catch(e => { /* handle the error */});
有一个共同点:顶级总是处理错误。