2015-12-02 16 views
7

Tôi có ba lời hứa, Phần còn lại yêu cầu trả lại danh sách dữ liệu.
Tài liệu thứ ba có các tham chiếu (id) cho hai danh sách đầu tiên, vì vậy tôi muốn ánh xạ các id này đến các tên tương ứng khi tôi có tất cả dữ liệu.
Ánh xạ không phải là vấn đề, tôi chỉ sử dụng Lodash cho điều đó.
Nhưng vấn đề là chờ đợi ba lời hứa sẽ giải quyết trước khi bắt đầu tính toán bản đồ này.RxJS: concat ba lời hứa, phân biệt kết quả

tôi đã tìm ra để sử dụng 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 
} 
); 

Vấn đề của tôi là onNext() sẽ được gọi theo thứ tự ngẫu nhiên. I E. Tôi không biết danh sách nào tôi nhận được tại một thời điểm nào đó và rất khó để biết được dữ liệu chứa trong đó.

Có cách nào để theo dõi lời hứa được tạo ra trong danh sách nào không? Một loại zip? concatMap? concatMapObserver? Tôi thừa nhận tôi chưa hoàn toàn hiểu được cách sử dụng của hai cái cuối cùng ...

Trả lời

6

Nếu đây là những lời hứa chúng tôi đang nói đến, tôi nghĩ bạn có thể xem nhà điều hành forkJoin. Cf. 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

Sau đó bạn có thể có một cái gì đó như:

Rx.Observable.forkJoin(p1, p2, p3, function(p1,p2,p3){ 
/* your combining code here */ 
}) 

Nói tóm lại, forkJoin có ngữ nghĩa tương tự như của RSVP.all nếu bạn biết những lời hứa thư viện RSVP.

+0

Cảm ơn. Tôi tìm ra cách concat thực sự hoạt động (xem câu trả lời của tôi), nhưng tôi thích forkJoin, tương ứng với những gì tôi muốn. Tôi hoàn toàn bỏ qua này ... :-) – PhiLho

+1

Nếu ai đó đang cố gắng để làm việc trong Angular, nó sẽ không, như "hoàn thành" sự kiện không được kích hoạt từ các quan sát http. Đối với một giải pháp tương tự, nó đã làm việc cho tôi bằng cách sử dụng "combinedLatest" thay thế. – frandevel

4

tôi đã thực hiện một số thí nghiệm sáng nay, trước khi đi để xem nếu tôi có một câu trả lời ... :-)

Bạn có thể nhìn thấy chúng ở http://plnkr.co/edit/3Xczzw

tôi phát hiện ra rằng concat của quan sát sẽ chạy mỗi lần lượt theo dõi, theo thứ tự đã cho.

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

cho

{"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 

Một concat những lời hứa sẽ không cung cấp bất cứ điều gì trước lời hứa đầu tiên giải quyết. Sau đó, nó có thể cung cấp (tức là gọi onNext) các lời hứa khác đã giải quyết, vẫn theo thứ tự đã cho. Sau đó có thể chờ đợi lời hứa tiếp theo nếu có hài cốt vv

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

cho

{"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 

hoặc

{"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 

Vì vậy, về cơ bản, concat tôn trọng trật tự của đối số của nó, có thể là một cách để tìm lại yêu cầu nào đã đưa ra kết quả hứa hẹn.
Trong trường hợp của các yêu cầu Ajax, tốt hơn concat những lời hứa hơn quan sát, vì chúng sẽ được yêu cầu song song, không tuần tự (trừ khi bạn cần thứ hai, tất nhiên).

Tôi đã thử giải pháp được đưa ra bởi @ user3743222 và đây là một giải pháp hay. Tôi thích forkJoin, vì các kết quả được gán rõ ràng cho các tham số, thay vì dựa vào thứ tự.

Bạn phải nhận thức được sự khác biệt trong quản lý lỗi: Tôi phát hiện ra rằng concat sẽ xử lý tất cả các lời hứa, cho đến khi tìm thấy lỗi đầu tiên. Trong khi forkJoin sẽ không xử lý bất cứ điều gì nếu một trong những lỗi hứa hẹn. Điều này có ý nghĩa (chúng tôi không thể tham gia một phần kết quả, nói chung).

+0

Thử nghiệm tốt đẹp. Tôi cũng sẽ thêm rằng với việc thực hiện những thứ tuần tự, bạn sẽ nhận được kết quả của bạn chậm hơn nếu bạn thực hiện chúng song song. – user3743222

Các vấn đề liên quan