RxJS:连接三个承诺,区分结果
RxJS: concat three promises, distinguish results
我有三个promise,Rest请求返回数据列表
第三个列表有对前两个列表的引用(id),所以当我拥有所有数据时,我想将这些id映射到相应的名称
映射不是问题,我只是使用Lodash
但问题是,在开始计算这个映射之前,要等待这三个承诺得到解决。
我想用concat()
:
Rx.Observable.concat(p1, p2, p3).subscribe(
function onNext(list)
{
// Assign the list to the corresponding variable in the scope
},
function onError(e)
{
// Notify of error
},
function onCompleted()
{
// Do the mapping
}
);
我的问题是onNext()
将按随机顺序调用。我不知道在某个时候我收到了哪个列表,而且很难从其中包含的数据中分辨出来。
有没有办法追踪哪些承诺产生了哪些清单?一种拉链?concatMap?concatMapObserver?我承认我还没有完全理解后两个的用法。。。
如果这些是我们正在讨论的承诺,我想您可以看看forkJoin
运算符。查阅https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/forkjoin.md,http://xgrommx.github.io/rx-book/content/observable/observable_methods/forkjoin.html
然后你可以有这样的东西:
Rx.Observable.forkJoin(p1, p2, p3, function(p1,p2,p3){
/* your combining code here */
})
简而言之,如果您知道promise库RSVP,那么forkJoin
的语义与RSVP.all
的语义相似。
今天早上我做了一些实验,然后去看看我是否有答案…:-)
你可以在http://plnkr.co/edit/3Xczzw
我发现,concat的可观测性将按给定的顺序依次运行每个可观测性。
var o1 = Rx.Observable.interval(1500).take(1).map(function (i) { return { n: i, id: 'First', ts: Date.now() - reference }});
var o2 = Rx.Observable.interval(1000).take(2).map(function (i) { return { n: i, id: 'Second', ts: Date.now() - reference }});
var o3 = Rx.Observable.interval(2000).take(1).map(function (i) { return { n: i, id: 'Third', ts: Date.now() - reference }});
// Alternative
var oa = Rx.Observable.timer(1200).map(function (i) { return { n: i, id: 'Alternative', ts: Date.now() - reference }});
Rx.Observable.concat(o1, o2, o3, oa).subscribe(
function onNext(v) { v.timestamp = Date.now() - reference; showObject(v); },
function onError(e) { var ts = Date.now() - reference; showHTML("Error " + JSON.stringify(e) + " at " + ts); },
function onCompleted() { var ts = Date.now() - reference; showHTML("Completed at " + ts); }
);
给出
{"n":0,"id":"First","ts":1503,"timestamp":1503}
{"n":0,"id":"Second","ts":2504,"timestamp":2504}
{"n":1,"id":"Second","ts":3505,"timestamp":3505}
{"n":0,"id":"Third","ts":5506,"timestamp":5506}
{"n":0,"id":"Alternative","ts":6708,"timestamp":6708}
Completed at 6708
在第一个承诺解决之前,一连串的承诺不会带来任何结果。然后,它可以交付(即调用Next)其他已解决的承诺,仍然按照给定的顺序。然后可以等待下一个承诺,如果还有,等等
var p1 = promiseInTime(1500, { id: 'First'});
var p2 = promiseInTime(1000, { id: 'Second' });
var p3 = promiseInTime(2000, { id: 'Third' });
var pa = promiseInTime(1200, { id: 'Failed? ' + !!withFailure }, withFailure);
Rx.Observable.concat(p1, p2, p3, pa).subscribe(
function onNext(v) { v.timestamp = Date.now() - reference; showObject(v); },
function onError(e) { var ts = Date.now() - reference; showHTML("Error " + JSON.stringify(e) + " at " + ts); },
function onCompleted() { var ts = Date.now() - reference; showHTML("Completed at " + ts); }
);
给出
{"id":"First","promiseTimeout":1500,"timestamp":1501}
{"id":"Second","promiseTimeout":1000,"timestamp":1506}
{"id":"Third","promiseTimeout":2000,"timestamp":2001}
Error {"id":"Failed? true","promiseTimeout":1201} at 2004
或
{"id":"First","promiseTimeout":1500,"timestamp":1501}
{"id":"Second","promiseTimeout":1000,"timestamp":1503}
{"id":"Third","promiseTimeout":2000,"timestamp":2000}
{"id":"Failed? false","promiseTimeout":1201,"timestamp":2004}
Completed at 2004
因此,基本上,concat尊重其参数的顺序,这可以作为一种查找哪个请求发出了promise结果的方法
在Ajax请求的情况下,与observable相比,更好地连接promise,因为它们将被并行请求,而不是按顺序请求(当然,除非您需要后者)。
我尝试了@user3743222给出的解决方案,这是一个不错的解决方案。我更喜欢forkJoin,因为结果被显式地分配给参数,而不是依赖于顺序。
您必须注意错误管理中的差异:我发现concat将处理所有承诺,直到发现第一个错误。而如果其中一个promise出错,forkJoin将不会处理任何内容。这是有道理的(一般来说,我们不能连接部分结果)。
- 承诺,如果第一个失败,则返回第二个承诺结果
- 不要在顺序链式承诺中包含 q 承诺结果
- Javascript承诺-检索结果
- JQuery 承诺:访问外部变量或将结果传递给 .done 内部的 IIFE
- 进行多个 http 调用并使用承诺合并结果
- 是否有可能将承诺的结果作为论据传递给 IIFE
- 为什么同步使用承诺会返回异步结果
- 如何返回嵌套承诺的结果
- 如何使用 Parse.promise javascript 定义一个承诺数组并获取结果数组 [parse.com]
- NodeJS 流解析并根据承诺结果逐行写入 json
- 承诺链接:在next-then回调中使用上一个承诺的结果
- 所有的承诺取决于另一个承诺的结果
- 将递归承诺的结果添加到数组中
- RxJS:连接三个承诺,区分结果
- 承诺在以不同方式执行时显示不同的结果
- AngularJS$http结果与承诺
- 从方法返回承诺结果
- 收集多个承诺结果?(纯javascript)
- 中继Q承诺结果到另一个承诺
- 根据承诺结果向动态ng表添加列