Reputation: 24472
I have 2 observables, and I need to get each observable data only one time.
What I did is subscription inside a subscription, although they can be executed in the same time (in parallel).
let table = this.af.database.object('tables');
table.subscribe((tableData) => {
let section_seats = this.af.database.object('sections').take(1)
.subscribe((sectionData) => {
//Here I'm Using tableData & sectionData
});
});
The code above works great, but they are not executed in the same time although they can.
How I can execute both of the observables in the same time then use the data received from both of them?
Update: Using forkJoin() doing nothing (no console log from the following code)
var source = Observable.forkJoin(
this.af.database.object('tables'),
this.af.database.object('sections')
);
var subscription = source.subscribe(
function (x) {
console.log('Next: %s', x);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
Upvotes: 3
Views: 2011
Reputation: 131
try this:
var source = Observable.forkJoin(
this.af.database.object('tables'),
this.af.database.object('sections')
);
var subscription = source.subscribe(
data => {
console.log(data[0]);
console.log(data[1]);
},
err => console.error(err)
);
Upvotes: 0
Reputation: 18665
There are a number of ways (read, operators) which will help you combine sources. A general resource can be found here, in the section Combining multiple observable sequences into a single sequence
. For your specific problem, here is the short list that seems to make the cut :
For example: Rx.Observable.combineLatest(object('tables'), object('sections').take(1))
For example : object('tables').withLatesFrom(object('sections').take(1))
For example: Rx.Observable.zip(object('tables'), object('sections').take(1))
Each of those operators have similar but slightly different semantics. I would assume combineLatest
is what you need but check the doc, set up some code and try out something and if that does not work, come back and post it here.
Upvotes: 4
Reputation: 1083
The documentation for forJoin
explains it:
Runs all observable sequences in parallel and collect their last elements.
The last element I assume would be the last element fired before an observable completes, so all Observables that you pass to forkJoin
has to be completed before anything is emitted.
Since you only want the first emitted element try to make each Observable complete after its first emit:
var source = Observable.forkJoin(
this.af.database.object('tables').take(1),
this.af.database.object('sections').take(1)
);
Upvotes: 0
Reputation: 3305
You should use withLatestFrom
operator.
see here more on withLatestFrom
/* Have staggering intervals */
var source1 = Rx.Observable.interval(140)
.map(function (i) { return 'First: ' + i; });
var source2 = Rx.Observable.interval(50)
.map(function (i) { return 'Second: ' + i; });
// When source1 emits a value, combine it with the latest emission from source2.
var source = source1.withLatestFrom(
source2,
function (s1, s2) { return s1 + ', ' + s2; }
).take(4);
var subscription = source.subscribe(
function (x) {
console.log('Next: ' + x.toString());
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});
// => Next: First: 0, Second: 1
// => Next: First: 1, Second: 4
// => Next: First: 2, Second: 7
// => Next: First: 3, Second: 10
// => Completed
Upvotes: 0