逃离$ .ajax({success:function()})dungeon

时间:2012-03-07 20:40:28

标签: javascript jquery html ajax

所以我有一个常见的场景,一切都依赖于AJAX响应,然后可能有更多的AJAX响应。

最终发生的事情是在 success()回调中抛出了大量的演示文稿(特定于页面)代码:

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

从演示代码中完全删除此“数据访问”代码但保持加载顺序的最佳做法是什么?

我使用了$.when().then()之类的延迟通话,但这对我来说仍然很草率。还有什么更好的吗?

为了使答案更简单,假设我想要检索有关Person对象的信息,并将所有逻辑分离到自己的区域。例如:

注意:此代码无效 - 我知道

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);

编辑:我的解决方案

尽管许多答案都很有用,但我选择传递回调函数,将各种逻辑逻辑彼此分开。示例代码:

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);
}

我还应该补充一点,我发现这张幻灯片非常有用:

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

5 个答案:

答案 0 :(得分:4)

你必须在成功回调中有所作为,但你不需要那里的演示细节。成功通话可以简单地致电:

Person.render(attributes, element)

细节将在渲染功能中。

答案 1 :(得分:3)

正如SLaks所说,在AJAX的异步环境中你想做的事情是不可能的。

但是,没有任何事情可以反对将大部分代码保存在执行所有繁琐工作的单独对象中。然后,您将从成功回调中调用这些对象及其方法,并将所有必要的数据传递给它们。这将确保您的回调仅包含最少的代码。

答案 2 :(得分:2)

听起来您可能希望将Model-View-Controller design pattern引入您的应用程序中。在最简单的形式中,Model将负责获取所需的数据,然后将数据传递给要呈现的View; Controller的工作是处理传入的请求,调用Model并以预期的格式将数据混洗到View

正如其他人所提到的那样,JavaScript有很多lightweight MVC frameworks;但是你应该能够通过使用jQuery和模板引擎(例如Mustache.js)来启动和运行基本概念,这样你就可以在Model(获取数据和构建公共对象图)和View之间找到一些分离。 (渲染模板并将渲染的HTML添加到DOM中)。

至于你提出的Person示例,你可以使用jQuery's Deferred来允许Person.getById返回一个Promise,例如:

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's model data.
                    result = { 
                        id: response.id, 
                        name: response.firstName,
                        email: response.email
                    };

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

然后您的Controller可以调用Model,然后将结果提供给View(这是您可以使用模板的地方)。

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

答案 3 :(得分:1)

您可以稍微更改您的示例以使其异步工作 - 仍然比将所有内容推送到成功回调函数更简洁的代码:

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

答案 4 :(得分:0)

我现在知道正确的答案是:

  

专门为此创建了超过9000个库,这是一个常见问题,称为AMD。

-TerryR

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