カスタムライブラリなしでasync/awaitecma6標準を使用しています。
現時点では、エラーを適切にキャッチしてスローする方法がわかりません。複数のasync/await関数があり、重大なエラーが発生した場合は、エラーをすべての非同期関数の先頭にスローして、関数の実行を停止します。
Async/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);
}
(ノード:13964)UnhandledPromiseRejectionWarning:未処理のPromise拒否(拒否ID:1):エラー:getSessionID応答が未定義です(ノード:13964)[DEP0018] DeprecationWarning:未処理のPromise拒否は非推奨です。将来、処理されないPromise拒否は、ゼロ以外の終了コードでNode.jsプロセスを終了します。デバッガーが付属しています。
したがって、非同期関数から例外をスローしたり、node.jsのpromiseのcatchブロックで例外を再スローしたりすることは許可されていないようです。
では、どうすればこれを機能させることができますか? async関数でエラーをキャッチし、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;}
}
しかし、これは、最初の非同期関数からの呼び出しスタックでは、すべての関数が非同期である必要があり、実際には必要ない場合でも、約束を待たなければならないことを意味します。
誰かが私を啓発してくれることを願っています。
よろしくルヴィ
基本的なコールスタックの擬似コードを編集します。
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; }
}
async
/await
の優れた点の1つは、try
/catch
が非同期コードを処理できることです。
最初のbasicAuthLogin
関数はまったく問題ありません(getSessionID
が同期関数である場合)。 そうでない場合は、[あなたは今それがそうだと言った])。コードusingawait
がありません。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 */ });
それを使用するコードがこれらの2つのことのいずれかを実行する場合(またはエラーをこれらの2つのことのいずれかを実行するコードに伝播させる場合)、「未処理の拒否」エラーは発生しません。
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);
}
})();
ルールは例外を除いて同じです(概念的にはこれらのは例外であるため):
それを処理するか(例: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 */});
共通の分母は次のとおりです。トップレベルは常にエラーを処理します。