1. ホーム
  2. javascript

[解決済み] トップレベルでasync/awaitを使用するにはどうすればよいですか?

2022-03-16 09:01:32

質問

を調べてみました。 async / await で、いくつかの記事に目を通した後、自分でいろいろとテストしてみることにしました。しかし、なぜこれがうまくいかないのか、理解できないでいます。

async function main() {  
    var value = await Promise.resolve('Hey there');
    console.log('inside: ' + value);
    return value;
}

var text = main();  
console.log('outside: ' + text);

コンソールには以下のように出力されます (node v8.6.0) :

>外です。[オブジェクト プロミス]

> inside: こんにちわ

関数内のログメッセージは、なぜその後に実行されるのですか?と思ったのですが、理由は async / await は、非同期タスクで同期実行を行うために作成されたものである。

を使わずに、関数内で返された値を使用する方法はありますか? .then() の後に main() ?

解決方法は?

<ブロッククオート

なぜうまくいかないのか、理由がつかめません。

なぜなら main はプロミスを返します。 async 関数がそうです。

トップレベルでは、どちらかが必要です。

  1. トップレベルの async 関数は決して拒否しません("unhandled rejection"エラーが必要な場合を除きます)。

  2. 使用する thencatch または

  3. 使用方法 トップレベル await (ES2022、最近の環境では広くサポートされている) をトップレベルで使用できるようにするものである。 await をモジュールで使用することができます。

#1位 - トップレベル async 拒否しない関数

(async () => {
    try {
        var text = await main();
        console.log(text);
    } catch (e) {
        // Deal with the fact the chain failed
    }
})();

ここで catch を使用します。 しなければならない プロミスの拒否や非同期例外を処理することは、他の誰にもできません。もしあなたが望むなら、それを catch 関数(むしろ try / catch の構文)。

(async () => {
    var text = await main();
    console.log(text);
})().catch(e => {
    // Deal with the fact the chain failed
});

...これはもう少し簡潔なものです(私はそのためにこの方法が好きです)。

もちろん、エラーを処理せず、"unhandled rejection"エラーだけを許容することも可能です。

#2 - thencatch

main()
    .then(text => {
        console.log(text);
    })
    .catch(err => {
        // Deal with the fact the chain failed
    });

catch ハンドラは、チェーンの中でエラーが発生した場合や then ハンドラを使用します。(必ず catch ハンドラがエラーを投げないようにするためです)。

の両引数、または then :

main().then(
    text => {
        console.log(text);
    },
    err => {
        // Deal with the fact the chain failed
    }
);

再度、拒否ハンドラを登録していることに注意してください。しかし、このフォームでは then コールバックがエラーを投げなければ、エラーを処理するために何も登録されていません。

#3 トップレベル await モジュール内

を使用することはできません。 await は非モジュールスクリプトのトップレベルでありながら トップレベル await を使用すると、モジュールのトップレベルで使用することができます。これは、トップレベルの async 関数ラッパー (上記#1) の場合、トップレベルのコードで拒否 (エラーを投げる) したくはないでしょう。なぜなら、処理されない拒否エラーが発生してしまうからです。つまり、#1 のようにうまくいかないときに処理されない拒絶反応を起こしたくないのであれば、 エラーハンドラでコードを包むのがよいでしょう。

// In a module, once the top-level `await` proposal lands
try {
    var text = await main();
    console.log(text);
} catch (e) {
    // Deal with the fact the chain failed
}

このようにすると、あなたのモジュールからインポートしたモジュールは、あなたが作成した await を使用しているモジュールは、トップレベルの await が評価されると、基本的にモジュールローダーにプロミスを返します(たとえば async 関数は、その約束が完了するまで、それに依存しているモジュールのボディを評価する前に待機します。