web-dev-qa-db-ja.com

ParsePromiseチェーンに追加のデータを渡す方法

私のParseCloudeコードでは、それぞれが「find()」を使用して、いくつかの連続したクエリを実行する必要があります。

例:

var promise = firstQuery.get(objectId).then(function(result1){
            return secondQuery.find();
        }).then(function(result2){
            return thirdQuery.find();
        }).then(function(result3) {

             // here I want to use "result1", "result2" and "result3"
        });

問題は、親スコープで宣言された変数に割り当てずに、最後の「then」ステートメントで「result1」と「result2」にアクセスするにはどうすればよいかということです。

なぜ私はこれを尋ねるのですか:並列で実行するためにループ内に作成した一連のpromiseをネストしている場合、親スコープのトリックを使用することはできません(すべてのpromiseが次のようになる上記のステートメントの周りのforループを想像してください配列に入れてから、「Parse.Promise.when」を使用して評価します。これらはすべて、親スコープ変数の変更を同時に開始します。)

次の行に沿って何かを返すことができる、ある種のpromiseオブジェクトを作成できますか?

Parse.promise({result:result1,findResult:secondQuery.find()};

したがって、「result2」パラメータから値を取得するには、

result2.result 

そして

result2.findResult

私は自分自身を明確にしたいと思います。これを説明するのは簡単ではありません。

14
Joris Mans

closures を使用して、追加のオブジェクトやラッピングを必要とせずにこれを行うことができます。

var promise = firstQuery.get(objectId).then(function(result1){
    return secondQuery.find()
    .then(function(result2) {
        return thirdQuery.find()
        .then(function(result3) {
            //can use result1, result2, result3 here
        });
    });
});

この「ネストされた」構文は、機能的には「チェーン」構文と同じです。


コメントに基づいて編集

プロミスチェーンが長くて複雑で、このネストされた構文が不自然になる場合、ロジックはおそらく、それ自体の関数への抽象化に値するほど複雑です。

function complexQuery(objectId) {
    var results = {};
    return firstQuery.get(objectId).then(function(result1) {
        results.result1 = result1;
        return secondQuery.find();
    })
    .then(function(result2) {
        results.result2 = result2;
        return thirdQuery.find();
    })
    .then(function(result3) {
        results.result3 = result3;
        return results;
    });
}

complexQuery(objectId)
.then(function (results) {
    //can use results.result1, results.result2, results.result3
});

個人的には、.bindをいじるよりも読みやすく維持しやすいと思います。

24
Retsam

親スコープのトリックは使用できません

さて、他の両方の答えがこれを行うので、そうでない解決策を提案させてください。解決された約束を渡すことができます。これには、ネストやクロージャがないという追加の利点もあります。

これは、promiseはすでに値のプロキシであるという概念に基づいているため、実際には1つの長いチェーンを作成する必要はありませんhave

var firstObject = firstQuery.get(objectId);
var secondObject = firstObject.then(secondQuery.find.bind(secondQuery));
var thirdObject = secondObject.then(thirdQuery.find.bind(thirdQuery));
Promise.all(firstObject, secondObject, thirdObject).then(function(r1, r2, r3){
   // here you can use "r1", "r2" and "r3"
});

標準のpromiseでは、コードを解析するのではなく、これは次のようになります。

Promise.all([firstObject, secondObject, thirdObject]).then(function(){
   var r1 = arguments[0], r2 = arguments[1], r3 = arguments[2]; 
   // here you can use "r1", "r2" and "r3"
});

Bluebirdを使用すると、ショートカットに.spreadを使用したり、.bindまたは実際のコンテキストに使用したりできます。どうしても1つのチェーンを作成する必要がある場合は、Promise.allを使用して複数のpromiseを返すことでコンテキストを渡すことができますが、このアプローチが望ましいと思います。

12

ネストする代わりにフラットチェーン構文を維持したい場合は、親スコープのオブジェクトを使用して以下を共有できます。

var shared = {};
var promise = firstQuery.get(objectId).then(function(result1){
    // save results to shared object
    shared.result1 = result1;
    return secondQuery.find();
}).then(function(result2){
    shared.result2 = result2;
    return thirdQuery.find();
}).then(function(result3) {
    // here I want to use "result1", "result2" and "result3"
    // just use shared.result1, shared.result2
});
1
Timothy Walters