nerdlyist
nerdlyist

Reputation: 2847

jQuery Promise/Defered

I am using jQuery's getJSON method. Since it is asynchronous I am using the when method on the function that calls it to know when I can run my next function. The next function is to create a table using a handlebars template. I know the when is working because the template is created however I am not getting the data needed.

When using console.log I see the array attached to this but if I say this.objName it is undefined. So is the promise/deferred only saying that the request was successful? Is there a method that allows me to wait/watch for the data?

    (function () {
        "use strict";
        var TicketQueue = {
            init: function (config) {
                this.url = config.data;

                this.template = config.template;
                this.container = config.container;

                $.when(this.fetch()).done(this.attachTemplate());
            },
            attachTemplate: function () {
                var template = Handlebars.compile(this.template);

                this.container.append(template(this.tickets));

            },
            fetch: function () {
                var self = this;
                $.getJSON(this.url, function (data) {
                    self.tickets = $.map(data.tickets, function (ticket) {
                        return ticket;
                    });
                    //self.attachTemplate();
                });
            }
        };
        TicketQueue.init({
            template: $('#ticketQueueTpl').html(),
            container: $("table.ticketQueue"),
            data: "db/tickets.json"
        });
    }());

I have a comment self.attacheTemplate which does work but I am trying to make that function just the fetch and init initialize all of my code.

Upvotes: 2

Views: 240

Answers (1)

Matt
Matt

Reputation: 75317

  1. $.when() expects a Deferred as a parameter, otherwise it resolves straight away. Since you're not returning the AJAX promise from this.fetch(), the latter behaviour is been exhibited. Return the AJAX call from this.fetch().

    fetch: function () {
        var self = this;
        return $.getJSON(this.url, function (data) {
            self.tickets = $.map(data.tickets, function (ticket) {
                return ticket;
            });
            //self.attachTemplate();
        });
    }
    
  2. You're passing the result of this.attachTemplate() to then(), rather than the function itself. You want to be doing;

    $.when(this.fetch()).done(function () {
        this.attachTemplate()
    }.bind(this));
    

    Note I've stuck an extra bind() in there; that's because the value of this is lost in the anonymous function we're using.


Having said all of that, you don't even need $.when() in the first place; $.when() is good for combining multiple Deferreds into a single Deferred. Just use;

this.fetch().done(function () {
    this.attachTemplate();
}.bind(this));

Upvotes: 1

Related Questions