如何将额外数据传递到 Parse Promise 链 [重复]

Posted

技术标签:

【中文标题】如何将额外数据传递到 Parse Promise 链 [重复]【英文标题】:How to pass extra data down a Parse Promise chain [duplicate] 【发布时间】:2014-10-04 22:26:58 【问题描述】:

在我的 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”,而不将它们分配给在父作用域中声明的变量。

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

我可以创建某种承诺对象,我可以在其中返回类似于以下内容的内容:

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

所以我可以通过执行从“result2”参数中获取值

result2.result 

result2.findResult

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

【问题讨论】:

你是在第二个查询中使用第一个查询的结果吗?或者您是否可以并行运行所有三个查询,最后只检查所有三个查询的结果?如果是这样,有一种更快、更简单的方法来做到这一点。 所以你把我的问题标记为“之前被问过”,Bergi,而我的问题来自 2014 年 8 月,而你的问题来自 2015 年 1 月? @JorisMans:我确实将其标记为重复,即totally valid,因为另一个问题是关于该主题的规范问题(不确定您所说的“从技术上讲它们不是正确”)。我不得不承认,在创建规范问题时,我没有看到您的问题及其相当好的答案;我只是在使用搜索时遇到了你的。请注意,“之前询问”是known inacurracy,并不意味着日期对最终决定很重要。 【参考方案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
        );
    );
);

这种“嵌套”语法在功能上与您的“链接”语法相同。


基于 cmets 编辑

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

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 更容易阅读和维护。

【讨论】:

The Pyramid of Doom 我知道这行得通,但是当你疯狂地嵌套时,你最终会失去 Promise 的一大好处,如果你有 10 个,你不需要开始将它们嵌套到无穷大或多个连续调用。 @SecondRikudo 这并不像您想象的那么适用,除了“高度嵌套的代码丑陋且令人困惑”。你不能简单地通过显式定义命名回调函数来解决这个问题。 @JorisMans 个人而言,有 10 个异步调用需要按顺序运行(不能使用“Promise.all”),但不依赖于前一个调用的状态或不能t 将状态从回调传递到回调,这表明需要进行更大的重构,而不是链接 Promise 的巧妙方式。 例如创建一个封装了10步链的对象,并随身携带整个过程的状态。【参考方案2】:

你不能使用父作用域技巧

好吧,由于其他两个答案都这样做,所以让我提出一个没有的解决方案。您可以传递已解决的承诺。这还具有没有嵌套或闭包的额外好处。

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

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

【讨论】:

这在 Parse Cloud Code 中有效吗? 否则我不会以这种方式发布它【参考方案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
);

【讨论】:

如问题所述,我正在寻找没有父范围的解决方案。 你的父范围的问题需要澄清,如果“他们都同时修改父范围”真的是一个问题,那么各种共享访问都是一个问题。另请注意,promise 并不意味着多线程,您仍然一次只能执行一个,Parse.Promise.when() 将在链接到成功处理程序之前简单地处理它们。

以上是关于如何将额外数据传递到 Parse Promise 链 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

将额外参数传递给jquery ajax promise回调[重复]

如何将Promise值传递给一些独立的函数?- 脚本

Parse.Promise 已从类型定义中弃用/删除?

Mongoose Promise 不会将数据传递到下一个链

Parse.Promise已被弃用/从类型定义中删除?

如何将包装在 Promise 中的值传递给非异步函数? [复制]