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

Jor*_*ans 14 javascript promise parse-platform parse-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"
        });
Run Code Online (Sandbox Code Playgroud)

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

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

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

Parse.promise({result:result1,findResult:secondQuery.find()};
Run Code Online (Sandbox Code Playgroud)

所以我可以通过这样做从"result2"参数中获取值

result2.result 
Run Code Online (Sandbox Code Playgroud)

result2.findResult
Run Code Online (Sandbox Code Playgroud)

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

Ret*_*sam 24

您可以使用闭包来完成此操作,而无需任何额外的对象或包装.

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
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

这种"嵌套"语法在功能上与您的"链接"语法相同.


根据评论编辑

如果您的承诺链很长且足够复杂,以至于这种嵌套语法变得笨拙,那么逻辑可能足够复杂,值得将抽象转换为自己的函数.

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
});
Run Code Online (Sandbox Code Playgroud)

就个人而言,我认为这比阅读和阅读更容易阅读和维护.bind.


Ben*_*aum 12

您不能使用父范围技巧

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

这是基于promise已经代表值的概念,因此您实际上不必创建一个长链:

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"
});
Run Code Online (Sandbox Code Playgroud)

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

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"
});
Run Code Online (Sandbox Code Playgroud)

使用bluebird,您可以使用.spread快捷方式.bind或实际上下文.如果你绝对必须创建一个链,你可以通过使用Promise.all返回多个promise来传递上下文,但我相信这种方法更可取.