web-dev-qa-db-ja.com

解決済みのpromiseデータを同期的に使用する

私は約束について学び、続行する前に約束の使用を確実に理解していることを確認したいと思います。約束を返す機能を持ったオンラインサービスのライブラリを利用しています。

私が読んだほとんどすべての例は、チェーンされたthen()関数で解決されたデータを使用しています

const result = Library.functionReturningAPromise()
result.then(function(res) {
    const obj = new Example(res)
    return obj
}).then(function(ob) {
    // do the rest of the logic within these then() functions
})

または、解決されたデータをasync関数内で使用します

async function test() {
    const result = await Library.functionReturningAPromise()
    const obj = new Example(result)

    // do the rest of the logic
}

「通常の」同期コードで解決されたプロミスからのデータを使用する方法があるかどうか知りたい

 const result = Library.functionReturningAPromise()

 // do something to resolve the promise

 const obj = new Example(result)

または、常に「ラップ」する必要がある場合allasync関数で解決されたpromiseからのデータを使用するロジック。

6
myol

「通常の」同期コードで解決済みのプロミスからのデータを使用する方法があるかどうか知りたい

非同期応答を処理するときに完全に同期するコードを書く方法はありません。操作が非同期になると、非同期の手法を使用して応答を処理する必要があり、同期でプログラミングすることはできません。非同期プログラミングを学ぶ必要があります。

表示する2つのオプション(.then()または_async/await_)は、返されたpromiseを処理するための2つの選択肢です。

または、非同期関数の解決済みプロミスからのデータを使用するすべてのロジックを常に「ラップ」する必要がある場合。

awaitを使用して、promiseを処理するための同期的に見えるコードを記述できるようにする場合は、そのすべてのコードをasync関数内に含める必要があります。そして、その関数のスコープを離れると(値を返したいなど)、async関数からpromiseを返し、再びpromiseを処理する必要があります。

これを回避する方法はありません。これは、Javascriptで学ばなければならないものです。しばらくすると第二の性質になります。


ご存知のように、asyncawaitを使用して同期的に見えるロジックフローを取得できますが、これを行うときに理解しておく必要があることがいくつかあります。あなたの例から:

_async function test() {
    const result = await Library.functionReturningAPromise()
    const obj = new Example(result);

    // do the rest of the logic
}
_
  1. asyncで宣言されたすべての関数は、promiseを返します。それはあなたがそれらから得る唯一の種類の戻り値です。呼び出し元が戻り値を探している場合、または非同期操作が完了したとき、またはエラーを探しているときを知りたい場合は、.then().catch()、またはもう一度await関数内のasync
  2. 待機中のプロミスが拒否された場合、基本的には関数の残りの実行をスローして中止し、返されたプロミスを拒否して返します。
  3. 拒否されたpromiseで実行フローを中止し、呼び出し元が拒否を処理する場合は、それで問題ありません。
  4. ただし、発信者が拒否を処理していない場合は、誰かが処理する必要があります。 awaitを使用していて、拒否をローカルで処理する必要がある場合は、それらを_try/catch_でラップする必要があります(同期例外と非常によく似た構文)。

_try/catch_をawaitとともに使用してローカルでエラーを処理する例を次に示します。

_async function test() {
    try {
        const result = await Library.functionReturningAPromise()
        const obj = new Example(result);

        // do the rest of the logic
    } catch(e) {
        // handle promise rejection here
    }
}
_

呼び出し元によるエラー処理の例を次に示します。

_async function test() {
    const result = await Library.functionReturningAPromise()
    const obj = new Example(result);

    // do the rest of the logic
}

test().then(() => {
    console.log("all done");
}).catch(err => {
    console.log(err);
});
_
2
jfriend00

非同期コンテキストを「残す」場合は、Promiseが満たされるのを待つだけでよく、コールバックとして「通常の」関数の1つをthen()で呼び出します。

非同期のコーディングスタイルは非常に混乱する可能性があることは理解できますが、事実上、これはthen(function () {})の機能です。

このコーディングスタイルが理解または操作しやすい場合は、機能的に同等です。

function first() {
    console.log("sync!");
    doAsync();
}

function doAsync() {
    console.log("now we're async!");
    Library.functionReturningAPromise().then(second);
}

function second() {
    console.log("sync again!");
    // ...
}
1
FatalMerlin