Recursive XHR Call on a Sliding Interval

Preparing a demo for my talk titled “A Practical Overview of Actors in Service Fabric“, that was given at MSDEVMTL and that will be given at DevTeach 2016, I use TypeScript poll a REST API for new messages.

This experiment helped me understand => in TypeScript. Since I lost a few cycles trying to figure this out, I decided to share an example.

The Challenge

The following setTimeout continuously failed. I tried wrapping it with a function and it still had the wrong behavior.

setTimeout(this.refreshMeetingQuestions(), 1500);

After some bingle cycles, I finally understood that the reason I was getting this undesired behavior, I was getting the wrong reference to this

The function defined with arrow notation () => captures the reference to this when it is defined.

Therefore, the right way to call the refreshMeetingQuestions function is the following.

setTimeout(() => this.refreshMeetingQuestions(), 1500);

Let’s take a step back, and put the setTimeout function call in context. The following is the skeleton for my sliding interval recursive XHR call. The idea here is that I want the timeout to occur after I’m done processing the response. This also makes sure that I don’t make concurrent requests.

refreshMeetingQuestions() {
           $.ajax({
               method: "GET",
               url: this.nextStreamUri
           })
           .done(response => {
              // do something with the response
              // ...

              // store the URI for the next page  
              this.nextStreamUri = response.links[2].uri;
 
              // wait then call self
              setTimeout(() => this.refreshMeetingQuestions(), 1500);
            });
}

The BIG Picture

To put this experiment in context, I included the class below:

/// <reference path="../../typings/jquery/jquery.d.ts" />

module LiveQnA {

    export class Meeting {

        private meetingSelfLink: string;

        private participantId: string;

        private nextStreamUri: string;

        constructor(participantId: string, meetingSelfLink: string) {
            this.meetingSelfLink = meetingSelfLink;
            this.participantId = participantId;
        }

        refreshMeetingQuestions() {
            $.ajax({
                method: "GET",
                url: this.nextStreamUri
            })
                .done(response => {

                    for (var m in response.messages) {
                        var index = m;
                        if (response.messages.hasOwnProperty(m)) {
                            var message = $("<p><strong>" + response.messages[index].displayName + "</strong> asked <br/> " + response.messages[m].content + "</p>");
                            $("div#questions").append(message);
                        }
                    }

                    this.nextStreamUri = response.links[2].uri;

                    setTimeout(() => this.refreshMeetingQuestions(), 1500);
                });
        }

        loadMessageStream() {

            this.nextStreamUri = this.meetingSelfLink + "/stream";
            this.refreshMeetingQuestions();
        }
    }
}

// start polling for new questions

window.onload = () => {
    var meeting = new LiveQnA.Meeting("00-000-000","/api/meeting/00001");
    meeting.loadMessageStream();
};

2 responses to TypeScript – Recursive XMLHttpRequest (XHR) Call on a Sliding Interval

  1. 

    Thanks for the diversity and quality of your posts.

    Liked by 1 person

  2. 

    I suspect your first line, which is
    setTimeout(this.refreshMeetingQuestions(), 1500);
    was actually
    setTimeout(refreshMeetingQuestions, 1500);

    (no function invocation)

    I had the same situation arise in my code and solved it the same way. The other fix is to add .bind(this) on the end but the arrow function is more “typescripty” to me :)

    Thanks for sharing the post – glad to see someone else ran into the same issue and came up with the same solution.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.