Neil
Neil

Reputation: 413

Using debounce in rxjs client side webapp

I am moving into functional reactive code starting with rxjs and have some questions about how to best import it as I am getting mixed results.

Currently, I have a simple implementation where I check a web service for if a username already exists.

Here is the code that works perfectly:

$(window).load(function() {
    // setup an observable
    submission = Rx.Observable.fromEvent($("#submitbutton"), "click").map(
        event => {
            return "justsomeusername";
        }
    );

    submission
        .concatMap(username => {
            return Rx.Observable.fromPromise(
                $.get(
                    "{{ site.serveraddress }}/checkuser?&username=" + username
                )
            ).catch(() => Rx.Observable.empty());
        })
        .subscribe(rval => {
            console.log(rval);
        });
});

This all works great BUT when I try to add a debounce like submission.debounce(500).concatMap((username) =>

Rx.js:8512 Uncaught TypeError: this.durationSelector.call is not a function
at DebounceSubscriber._next (Rx.js:8512)
at DebounceSubscriber.Subscriber.next (Rx.js:424)
at MapSubscriber._next (Rx.js:5715)
at MapSubscriber.Subscriber.next (Rx.js:424)
at HTMLButtonElement.handler (Rx.js:3913)
at HTMLButtonElement.dispatch (jquery.min.js:3)
at HTMLButtonElement.r.handle (jquery.min.js:3)

That is what appears in the console.

I think that the way I am importing or referencing the library is the cause, this is where there is some confusion.

I am importing like this at the top of an HTML page:

<script src="https://unpkg.com/@reactivex/[email protected]/dist/global/Rx.js"></script>

If I try to import any other reference the Rx object seems not to exist? Does this have to do with the filename maybe becoming the object namespace?

For example, I downloaded all the latest rxjs release and in the dist see rx.all.js but if I import locally one of the latest dists like:

<script src="/myapp/javascript/rx.all.js"></script>

I get Rx undefined. What is the nuance occurring between these two different ways of reference.

What is the surefire way to import rxjs for client-side use? Is this the likely cause of the debounce not working (not having the full lib)?

Thanks!

Upvotes: 1

Views: 269

Answers (1)

Mark Hughes
Mark Hughes

Reputation: 7374

You should use debounceTime for this, not debounce. debounce takes a function parameter which must determine dynamically the debounce time, whereas debounceTime can be used exactly as you state:

$(window).load(function() {
    // setup an observable
    submission = Rx.Observable.fromEvent($("#submitbutton"), "click").map(
        event => {
            return "justsomeusername";
        }
    );

    submission
        .debounceTime(500)
        .concatMap(username => {
            return Rx.Observable.fromPromise(
                $.get(
                    "{{ site.serveraddress }}/checkuser?&username=" + username
                )
            ).catch(() => Rx.Observable.empty());
        })
        .subscribe(rval => {
            console.log(rval);
        });
});

If you wanted to use debounce, you'd do something like this:

    submission
        .debounce((val) => {
            // Add whatever logic for determining the right
            // debounce time for the value entered by the 
            // user, in this case, simply returning a hard
            // coded 500 which will do exactly the same as
            // debounceTime(500)
            return 500;
        })
        .concatMap(username => {
            // ... snip ...
        });
});

It doesn't look like there is any problem with how you are importing RxJS - although I would advise if you're just starting with RxJS to go to v6 as it changes how a lot of things are done with operators like debounce and concatMap - it's a pain to change it all later so better to make the change when you're just starting!

Upvotes: 1

Related Questions