如何将额外数据传递到 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 链 [重复]的主要内容,如果未能解决你的问题,请参考以下文章