Как передать дополнительные данные в цепочку Parse Promise

В моем коде Parse Cloude мне нужно запустить несколько последовательных запросов, каждый из которых использует "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"
        });

Возникает вопрос: как мне получить доступ к "result1" и "result2" в окончательном "then" -производстве, не присваивая их переменным, объявленным в родительской области.

Почему я спрашиваю об этом: вы не можете использовать трюк родительской области, если вы вставляете кучу promises, которую вы создаете в цикле, чтобы они выполнялись параллельно (представьте, что цикл for выше указанного утверждения в результате чего все promises помещаются в массив, а затем вычисляются с использованием "Parse.Promise.when". Все они будут одновременно модифицировать переменные родительской области.)

Можно ли создать какой-то объект обещания, где я мог бы что-то возвращать по строкам:

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

чтобы я мог получить значения из параметра "result2", выполнив

result2.result 

и

result2.findResult

Надеюсь, я разъясню. Это не очень легко объяснить.

Ответ 1

Вы можете использовать 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.

Ответ 2

Вы не можете использовать трюк родительской области

Хорошо, так как оба других ответа делают это, позвольте мне предложить решение, которое этого не делает. Вы можете передать разрешенный promises. Это также имеет дополнительное преимущество без гнездования или закрытия.

Это основано на концепции, что promises являются прокси-серверами для значений уже, поэтому вам фактически не нужно создавать одну длинную цепочку:

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"
});

В стандартном promises, а не в синтаксическом коде, это выглядит примерно так:

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 или фактического контекста. Если вы абсолютно должны создать одну цепочку, вы можете передать контекст, возвращая несколько promises с помощью Promise.all, но я считаю, что этот подход предпочтительнее.

Ответ 3

Если вы хотите сохранить синтаксис плоской цепочки вместо вложенности, вы можете использовать объект из родительской области для совместного использования:

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
});