関数の変数を返す前に、プロミスが完了するのをどのように待つのですか?


148

私はまだ約束に苦労していますが、ここのコミュニティのおかげである程度進歩しています。

Parseデータベースにクエリを実行する単純なJS関数があります。結果の配列を返すことになっていますが、クエリの非同期の性質(したがって、promise)のため、関数は結果の前に戻り、未定義の配列が残ります。

この関数にプロミスの結果を待機させるには、何をする必要がありますか?

これが私のコードです:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    var promise = query.find({
               success: function(results) {
               // results is an array of Parse.Object.
                             console.log(results);
                             //resultsArray = results;
                             return results;
               },

               error: function(error) {
               // error is an instance of Parse.Error.
                             console.log("Error");
               }
    });                           

}

3
async / awaitの使用も検討してください。ノードはバージョン7.6以降、そのままで非同期/待機をサポートするようになりました
Viliam Simko '19

回答:


66

resultsArray結果配列のプロミスを返す代わりthenに、呼び出しサイトでそれを返します-これは、関数が非同期I / Oを実行していることを知っている呼び出し側の追加の利点があります。JavaScriptでの同時実行のコーディングはそれに基づいています- より広いアイデアを得るためにこの質問を読むことをお勧めします:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    return query.find({});                           

}

// later
resultsByName("Some Name").then(function(results){
    // access results here by chaining to the returned promise
});

Parse自身のブログ投稿で、クエリで解析プロミスを使用するその他の例を確認できます。


これのサポートは何ですか?IE9はこれをサポートしていますか?
sandrina-p 2016

はい、でもParse自体はほとんど死んでいるので、@ SandrinaPereiraがあります。これはパースクラウドコードです。
Benjamin Gruenbaum 2016年

1
ああ、これは純粋なJavaScriptだけではないのですか?私はこれを行う方法を探していました(関数が別の関数を開始するのを待つ)が、純粋なjavascriptでのみ..
sandrina-p

問題はコードを解析することであり、約束ではありません。Promiseは(ライブラリがあれば)どのブラウザでも機能します。BluebirdはIE6およびnetscape 7で動作します
Benjamin Gruenbaum 2016年

1
私はSOを2日間読んでいますが、まだ誰もこれを解決していません。この受け入れられた答えは他のすべてと同じです。この関数は、OPが要求した値ではなく、Promiseを返します。なぜこの回答は承認済みとマークされているのですか?
iGanja

19

この関数にプロミスの結果を待機させるには、何をする必要がありますか?

使用async/await(ECMA6の一部ではありませんが、2017年末以降、Chrome、Edge、Firefox、Safariで使用可能です。canIuseを参照してください)
MDN

    async function waitForPromise() {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }

コメントにより追加:非同期関数は常にPromiseを返し、TypeScriptでは次のようになります。

    async function waitForPromise(): Promise<string> {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }

4
async関数は、待機なしで(または非同期コードで)呼び出された場合でも、promiseオブジェクトを返します。不明な場合は、console.log(waitForPromise())の結果を確認してください。async関数内でconsole.log(result)をチェックすると、期待どおりの結果出力されますが、async関数からの戻りはブロックせずにすぐに行われ、promiseを返します。JavaScriptでのブロックは、シングルスレッドアプリケーションであるため、通常は非常に良くありません。ブロックすると、他のpub / subクライアントの通知が枯渇し、アプリ全体が本質的に危険にさらされます。
SRM

1
.netは「約束」のようなタスククラスで.wait()を持っています。JavaScriptにこの機能はありませんか?出力を別のツールにパイプするノードコマンドラインツールを終了する前に、何かを待つ必要があります。「await」は非同期関数内でのみ機能します。つまり、約束の範囲外では機能しません。
TamusJRoyce 2018年

@SRM私はあなたのコメントがサンプルの誤った解釈に基づいているように感じます-これは「最も内側の」Promise.resolve(最も単純なPromiseの例として)に関するものなので、コメントで述べているように外部の呼び出し元はありません。だから私は答えを更新することにしました。
Martin Meeser

@TamusJRoyceそれはそれ自体が問題だと思いますが、C#ではTask.ContinueWith(Task)を使用できると思います。これは、受け入れられた回答( "then()"と呼ばれます)と同じ考え方です。
Martin Meeser

今見えると思います。スクリプト全体を1つの巨大な非同期関数でほぼラップできます。そして、その関数をスクリプトの最後の行として呼び出します。その機能は、まだボイラープレートの少しです。しかし、私が以前に認識したよりもはるかに少ない。関数内で関数を記述するのに慣れていません。@MartinMeeserありがとうございます!
TamusJRoyce

3

JavaScriptは非ブロッキングであることが意図されているため、関数を待機させたくありません。関数の最後にプロミスを返すのではなく、呼び出し元の関数はプロミスを使用してサーバーの応答を取得できます。

var promise = query.find(); 
return promise; 

//Or return query.find(); 

1
success:ビットを含むコールバック全体がオフになっています。
Benjamin Gruenbaum、2015年

以上:return query.find();
マッシュ

また大丈夫です。説明のためにこのままにしておきますが、コメントとして追加します。
2015年

私はこれを試しましたが、結果は未定義のようです。resultsByName( "name")。then(function(results){console.log( "got array" + results.count);});
mac_55、2015年

1
おかげで、results関数の内部になんらかのエラーがあったのではないでしょうか。それは今働いています。console.logをresults.lengthに変更し、返された配列に1つのエントリがあることを確認できます:)
mac_55

2

ここでは実際にはプロミスを使用していません。Parseでは、コールバックまたはプロミスを使用できます。あなたの選択。

promiseを使用するには、次のようにします。

query.find().then(function() {
    console.log("success!");
}, function() {
    console.log("error");
});

これで、promiseが完了した後に何かを実行するには、then()呼び出し内のpromiseコールバック内で実行するだけです。これまでのところ、これは通常のコールバックとまったく同じです。

プロミスを実際に活用するには、次のようにプロミスをチェーンする必要があります。

query.find().then(function() {
    console.log("success!");

    return new Parse.Query(Obj).get("sOmE_oBjEcT");
}, function() {
    console.log("error");
}).then(function() {
    console.log("success on second callback!");
}, function() {
    console.log("error on second callback");
});

結果オブジェクトはどのタイプのオブジェクトですか?私の配列が含まれていないようです
mac_55

の配列である必要がありParse.Objectます。
2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.