ie.
ie.

Reputation: 6101

Unexpected "then" call order with jQuery promises

I use jQuery promises to track some changes on the server. I also use typescript, so my example is in typescript.

I use the following method for tracking changes:

startObserve(): JQueryPromise<void> {
    console.info("initializing...");

    const that = this;
    let countdown = 3;

    return this.loadData()
        .then(baseData => {
            const checkChanges = () => {
                const d = $.Deferred();
                d.then(() => {
                    console.info("checking changes...");

                    return that.loadData()
                        .then(data => {
                            countdown--; // emulate check logic

                            console.info("next interation! countdown:", countdown);

                            if (countdown === 0)
                                return null;

                            return checkChanges();
                        });
                });
                setTimeout(d.resolve, 250);
                return d.promise();
            };

            return checkChanges();
        });
}

So I just recursively call checkChanges method, which returns new promise until some change detected.

Here is how I try to utilize the startObserve method:

    this.startObserve()
        .then(() => {
            console.info("change detected! we can continue!");
        }).fail(() => {
            console.error("something is very wrong!");
        });

I expect to get the following output:

initializing...
checking changes...
next interation! countdown: 2
checking changes...
next interation! countdown: 1
checking changes...
next interation! countdown: 0
**change detected! we can continue!**

But here is what I get:

initializing...
checking changes...
**change detected! we can continue!**
next interation! countdown: 2
checking changes...
next interation! countdown: 1
checking changes...
next interation! countdown: 0 

It look a bit strange for me. Where I am wrong? Here is jsfiddle showing the issue: https://jsfiddle.net/4dofznqL/1/

Upvotes: 0

Views: 46

Answers (1)

Aleksey L.
Aleksey L.

Reputation: 37988

You're returning promise resolved by timeout instead of chaining ajax promise:

...

const checkChanges = () => {
  const d = $.Deferred();
  setTimeout(d.resolve, 250);

  return d.then(() => {
    console.info("checking changes...");

    return that.loadData()
      .then(data => {
      countdown--;

      console.info("next interation! countdown:", countdown);

      if (countdown === 0)
        return null;

      return checkChanges();
    });
  });
};

...

Upvotes: 3

Related Questions