0

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?

1
  • Did you mean to surround the value with brackets in the let, creating a new object with a key of 'pdfObjects', or is that a typo when simplifying? Commented Jun 13, 2016 at 7:16

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks but it doesn't solve the problem here... observer.next() will simply return the pdf value in the subscribe of the forkJoin! What I need is that each observable has its own pdf variable as it argument.
I think that your problem is related to the use of closures within loops. I updated my answer accordingly...
Will the observables have a different pdf argument? The problem I see is that you're pushing the function with a pdf reference and that reference will change (it will be equal to the last pdfObjects item) when it will be executed by the forkJoin.
Am I missing something?
In fact, in this case, the variable wouldn't be bound to the variable outside the inner function (your problem). I added a plunkr in my answer ;-)
0

@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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.