Exception from $ .ajax ({success: function ()}) dungeon

So I have a general scenario where everything depends on AJAX responses and then maybe more AJAX responses.

The result is a multiple and multiple presentation of the (page-specific) code called in the success () callback :

 $.ajax({
     ...
     success: function (response) {
         // too much $('#something').html() crap goes in here!
     }
 });

      

What's the best practice to completely remove this data access code from the presentation code, while maintaining the load sequence?

I've used delayed calls such as $.when().then()

but it still seems sloppy to me. Anything better?

To make the answer even easier, let's say I want to get information about an object Person

and separate all this logic in my scope. Example:

note: this code won't work - I know that

Person.js:

var Person = {
    getByID: function(id) {
        // ajax call to return a person object (format is arbitrary)
        //   { id: 12345, name: 'Joe Smith', email: 'joe@smith.com }
    }
};

      

SomePage.html

var myID = 12345;  // get ID from wherever
var person = Person.getByID(myID);
$('#person .name').html(person.name);
$('#person .email').html(person.email);

      


EDIT: My solution

While many of the answers were helpful, I decided to pass in callback functions that separate all the different pieces of logic from each other. Sample code:

JS:

Person = {
    get: function(params, callback) {
         $.ajax({
            url: '/person/get',
            data: params,
            success: callback
         });
    }
};

Pages = {
    Person: {
        render: function(person) {
           // in reality I'm using templates, this is for simplicity
           $('#person .name').html(person.name);
           $('#person .email').html(person.email);
        }
    }
};

      

SomePage.html

$('#someElement').someEvent(function() {
    var params = {
        id: 12345
    };

    Person.get(params, Pages.Person.render);
}

      

I should also add that this slide is extremely informative:

http://speakerdeck.com/u/addyosmani/p/large-scale-javascript-application-architecture

+3


source to share


5 answers


Now I know the correct answer:

There are over 9000 libraries built specifically for this, a common problem known as AMD.



-TerryR

http://speakerdeck.com/u/addyosmani/p/large-scale-javascript-application-architecture

0


source


You should end up with something in the success callback, but you don't need the presentation data. Calling the call can simply be called:

Person.render(attributes, element)

      



And the details will be in the render function.

+4


source


As SLAX says, what you want to do is not possible in an asynchronous AJAX context.

However, there is nothing against having most of the code in separate objects that do all the nagging work. Then you call these objects and their methods from your success callbacks and pass all the data you need to them. This will ensure that your callbacks only contain minimal code.

+3


source


It seems to me that you can introduce the Model-View-Controller design pattern into your application. In its simplest form, it Model

will be responsible for fetching the required data, which is then passed to View

for display; the job Controller

is to process incoming requests, call Model

and shuffle the data in View

the expected format.

As mentioned, there are many lightweight MVC frameworks for JavaScript ; but you have to get the basic concept and run it with jQuery and a templating engine (like Mustache.js ) so you can get some separation between the model (fetching the data and building a common object graph) and the view (rendering the template and adding the rendered HTML to DOM).

Regarding the Person example you suggested, you can use jQuery Deferred so that you Person.getById

can return a Promise, like so:

var Person = {
    getByID: function(id) {
        var result;

        // Return a Promise which we will resolve once the AJAX call completes.
        return $.Deferred(function (dfd) { 
            $.ajax(...)
                .done(function (response) { 
                    // Parse the AJAX response into your app model data.
                    result = { 
                        id: response.id, 
                        name: response.firstName,
                        email: response.email
                    };

                    // Resolve the Promise and supply the Person object.
                    dfd.resolve(person);
                });
        }).promise();
    }
};

      

Then yours Controller

can call Model

and then pass the result to View

(you can use templates here).

Person.getByID(myID)
    .done(function(person) { 
        $('#person .name').html(person.name);
        $('#person .email').html(person.email);
    });

      

+2


source


You can modify your example slightly to make it work asynchronously - still cleaner code than switching to a callback function:

var myID = 12345;  // get ID from wherever
Person.getByID(myID, function(person) {
    $('#person .name').html(person.name);
    $('#person .email').html(person.email);
});

      

+1


source







All Articles