VIDesignz VIDesignz - 3 months ago 13
Javascript Question

Exposing public methods after an ajax call within a closure

So I am finally at a loss and am here for a little guidance.

To sum up the idea, I am writing a small bit of code within a closure that uses an ajax call to fetch feedback. The code will be used like so...

var myFeedback = feedback();


Then I need a few methods exposed that will be called like so...

myFeedback.successMessages();


Which will return an array of only the success messages. There will be a method for error messages, info messages, and all messages.

I can easily write it if the whole feedback object was hard coded, my problem is that the feedback object is pulled from an ajax call. Searching and trying different solutions for the past 6 or so hours, I have finally been able to arrange the function where all the values from the ajax call are set properly and the rest of the functions are running in their proper order.

So on with the issue that I can not wrap my head around...How in the world do I return the methods object to expose them? Before the ajax call it was easy, but do to the async nature, I have to put the return inside another function, but I can't seem to return it all the way to the base
feedback()
function. I have tried many many of ways but still no success.

Currently, the error I get is
Type error feedback(...) is undefined


I had it at one point where
feedback()
was correct but would get an error about the method I was trying to access...
successMessages is not a function


Well, enough of the talk....here is the code. As you can see, my final feeble attempt was to return like so...

methods => getFeedback => feedback


I am far from great at understanding in returns for chaining and exposing except for the basics so I am hoping you guys can shed some light on my issue.

var feedback = function() {

var methods = null;

var getFeedback = function (callback) {

$.ajax({
type: "GET",
url: '<?= Config::get('URL') ?>ajax/feedback',
dataType:"json",
}).done(function(response) {

console.log("Step 1: Retrieve Messages");
callback(response);

}).always(function(){

console.log("Step 3: Return Methods");
console.log(methods);
return methods;

});

}

return getFeedback(function(response) {

console.log("Step 2: Log Response");
console.log(response);

methods = {
"successMessages" : function() {
console.log(response.success);
},
"errorMessages" : function() {
console.log(response.error);
},
"infoMessages" : function() {
console.log(response.info);
},
"allMessages" : function() {
console.log(response);
},
};

});

};


I should note, I will be adding validation regarding ajax results and such but for now I just need to get past this roadblock.

Thank you all in advance!!

Answer

Using the fact that jquery.ajax returns a promise, makes this code rather more simple than you may have thought

var feedback = function() { 
    var feed = $.ajax({
        type: "GET",
        url: '<?= Config::get('URL') ?>ajax/feedback',
        dataType:"json",
    });

    return {
        "successMessages" : function(callback) {
            feed.then(function(response) {
                callback(response.success);
            });
            // note 1
        },
        "errorMessages" : function(callback) {
            feed.then(function(response) {
                callback(response.error);
            });
            // note 1
        },
        "infoMessages" : function(callback) {
            feed.then(function(response) {
                callback(response.info);
            });
            // note 1
        },
        "allMessages" : function(callback) {
            feed.then(function(response) {
                callback(response);
            });
            // note 1
        }
    };  
};

usage would be

var myFeedback = feedback();

myFeedback().successMessages(function(success) {
    console.log(success);
});

myFeedback().errorMessages(function(error) {
    console.log(error);
});

myFeedback().infoMessages(function(info) {
    console.log(info);
});

myFeedback().allMessages(function(response) {
    console.log(response);
});

If you return feed; where I've got note 1 you can make it even simpler

var myFeedback = feedback();

myFeedback().successMessages(function(success) {
    console.log(success);
}).errorMessages(function(error) {
    console.log(error);
}).infoMessages(function(info) {
    console.log(info);
}).allMessages(function(response) {
    console.log(response);
});
Comments