如何在Parse Promise链中传递额外数据

时间:2014-08-12 00:15:43

标签: javascript parse-platform promise cloud-code

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

问题是:如何在最后的“then”语句中访问“result1”和“result2”,而不将它们分配给父作用域中声明的变量。

为什么我这样问:如果要在循环中创建一堆promises以便它们并行执行,那么你就不能使用父作用域技巧(想象一下围绕上述语句的for循环所有将promise放入一个数组中,然后使用“Parse.Promise.when”进行评估。它们都将同时开始修改父作用域变量。)

我可以创建某种承诺对象,我可以返回以下内容:

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

所以我可以通过

从“result2”参数中获取值
result2.result 

result2.findResult

我希望我能说清楚。这不是很容易解释的。

3 个答案:

答案 0 :(得分:24)

您可以使用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更容易阅读和维护。

答案 1 :(得分:12)

  

您不能使用父范围技巧

好吧,既然其他答案都是这样做的,那么让我建议一个没有的解决方案。你可以传递已解决的承诺。这也具有无嵌套或封闭的额外好处。

这是基于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"
});

在标准承诺中,而不是解析代码,这看起来很相似:

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或实际上下文。如果你绝对必须创建一个链,你可以通过使用Promise.all返回多个promise来传递上下文,但我相信这种方法更可取。

答案 2 :(得分:1)

如果要保留扁平链式语法而不是嵌套,可以使用父作用域中的对象进行共享:

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