0

I'm a bit new to RxJS and it is kicking my ass, so I hope someone can help!

I'm using RxJS(5) on my express server to handle behaviour where I have to save a bunch of Document objects and then email each of them to their recepients. The code in my documents/create endpoint looks like this:

    // Each element in this stream is an array of `Document` model objects: [<Document>, <Document>, <Document>] 
    const saveDocs$ = Observable.fromPromise(Document.handleCreateBatch(docs, companyId, userId));

    const saveThenEmailDocs$ = saveDocs$
      .switchMap((docs) => sendInitialEmails$$(docs, user))
      .do(x => {
        // Here x is the `Document` model object
        debugger;
      });

    // First saves all the docs, and then begins to email them all.
    // The reason we want to save them all first is because, if an email fails,
    // we can still ensure that the document is saved
    saveThenEmailDocs$
      .subscribe(
        (doc) => {
          // This never hits
        },
        (err) => {},
        () => {
          // This hits immediately.. Why though?
        }
      );

The sendInitialEmails$$ function returns an Observable and looks like this:

  sendInitialEmails$$ (docs, fromUser) {
    return Rx.Observable.create((observer) => {

      // Emails each document to their recepients
      docs.forEach((doc) => {
        mailer.send({...}, (err) => {
          if (err) {
            observer.error(err);
          } else {
            observer.next(doc);
          }
        });
      });

      // When all the docs have finished sending, complete the
      // stream
      observer.complete();
    });
  });

The problem is that when I subscribe to saveThenEmailDocs$, my next handler is never called, and it goes straight to complete. I have no idea why... Inversely if I remove the observer.complete() call from sendInitialEmails$$, the next handler is called every time and the complete handler in subscribe is never called.

Why isn't the expected behaviour of next next complete happening, instead it's one or the other... Am I missing something?

Johnny Ji
  • 169
  • 2
  • 11

1 Answers1

0

I can only assume that mailer.send is an asynchronous call. Your observer.complete() is called when all the asynchronous calls have been launched, but before any of them could complete.

In such cases I would either make an stream of observable values from the docs array rather than wrap it like this.

Or, if you would like to wrap it manually into an observable, I suggest you look into the library async and use

async.each(docs, function(doc, callback) {...}, function finalized(err){...})
Ben Dadsetan
  • 1,565
  • 11
  • 19