Reputation: 7856
I'm using a forkJoin
of observables but I'm having troubles to pass arguments in my observables. Lines of code worth a thousand words:
for(var key in pdfObjects){
let pdf = {pdfObjects[key]};
observables.push(new Observable(observer => {
this.createPDF(pdf).subscribe((pdfFile) => {
// Do something with my pdfFile
observer.complete();
})
})
}
Observable.forkJoin(observables).subscribe(
(next) => {},
(error) => {},
(completed) => {
console.log('completed');
}
);
(I have simplified the code for better clarity)
As you can see here, the problem is that when the code executes the observables, the pdf
variable is equal to the last pdfObjects
instead of being a different variable for each observable.
The question is how can I 'pass' and 'copy' my pdf
variable so it's a diffent one for each observable?
Upvotes: 0
Views: 868
Reputation: 29194
@Thierry is right, here's an example to show what's going on (fiddle)
var pdfObjects = {
a: 'Object A',
b: 'Object B',
c: 'Object C'
};
for(let key in pdfObjects) {
let pdf = pdfObjects[key];
function createObservable(p) {
console.log('createObservable:', p, pdf, key);
return Rx.Observable.create(observer => {
console.log('createObservable.create:', p, pdf, key);
observer.onNext({ p: p, pdf: pdf, key: key});
observer.onCompleted();
});
}
observables.push(createObservable(pdf));
}
Result:
createObservable: Object A Object A a
createObservable: Object B Object B b
createObservable: Object C Object C c
createObservable.create: Object A Object C c
createObservable.create: Object B Object C c
createObservable.create: Object C Object C c
When createObservable
is called, each value is as you would expect. But when you subscribe to your observables, the anonymous function that takes observer
is called by RxJs and is using the current values for pdf
and key
which are what they were the last time through the loop. But because you're creating a function, there's a new scope and the argument 'p' in that scope is the value the function was called with.
Upvotes: 0
Reputation: 202138
You should call the next
method instead of the complete
one:
observables.push(new Observable(observer => {
this.createPDF(pdf).subscribe((pdfFile) => {
// Do something with my pdfFile
observer.next(pdf); // <-----
});
})
Edit
Your problem is related to the use of closures within loops.
You could break with a method:
createObservable(pdf:any) {
return new Observable(observer => {
this.createPDF(pdf).subscribe((pdfFile) => {
// Do something with my pdfFile
observer.complete();
});
});
}
otherMethod() {
for(var key in pdfObjects){
let pdf = {pdfObjects[key]};
observables.push(this.createObservable(pdf));
}
(...)
}
See this question for more details:
See this plunkr: https://plnkr.co/edit/P4BfwnA1HEw7KU4i3RbN?p=preview.
Upvotes: 4