关于javascript:等待ajax返回的正确方法(我不想使用成功处理程序。)

Correct way to wait for ajax to return (I don't want to use the success handler.)

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
How can I get jQuery to perform a synchronous, rather than asynchronous, AJAX request?
how to wait for an ajax call to return

听我说完。我完全理解这个代码段。

1
2
3
4
5
6
$.getJSON(someURL, function(data){
    //do something with my data
})
.success(function () {
    //Call what you want on success
})

如果我只需要执行一个非常静态的操作,这看起来很好。但是,如果我想减少限制,比如

1
2
3
4
5
function my_func(){
    $.getJSON(someURL, function(data){
        //do something with my data... like modify an array or the dom
    })
}

现在司机

1
2
my_func();
//Now I want to call a function that relies on the data that my_func brought into the script.

如果我想这样做,我编写脚本的方式有什么问题吗?或者我只是缺少一些很棒的内置方法?


我看到两种可能的jquery-ish方法。

第一种方法是使用可传递给my_func的另一个回调:

1
2
3
4
5
6
7
8
9
10
function my_func(callback) {
    $.getJSON(someUrl, function(data) {
        // ...do stuff ...
        if ($.isFunction(callback)) { callback(data); }
    });
}

my_func(function(data) {
    // ..do more stuff..
});

第二种方法是创建一个自定义事件,该事件在my_func内部触发,并且可以从外部收听:

1
2
3
4
5
6
7
8
9
10
11
function my_func() {
    $.getJSON(someUrl, function(data) {
        $(document).triggerHandler('my_func:data-received', [data]);
    });
}

$(document).on('my_func:data-received', function(event, data) {
    // ...do stuff...
});

my_func();

我强烈建议只有在绝对必要的情况下才使用async: false

处理这个问题的另一种方法是jquery.deferred对象:

1
2
3
4
5
6
7
8
9
10
11
function my_func() {
    var d = new $.Deferred();
    $.getJSON(someUrl, function(data) {
        d.resolve(data);
    });
    return d;
}

my_func().done(function(data) {
    // ...do stuff...
});

函数返回允许注册回调的对象。在函数中,您只需要确保调用resolve来调用所有注册的done回调处理程序。


然后是xhr对象:

1
var jqXHR = $.getJSON(someURL);

定义之后,您可以在任何地方访问它:

1
2
3
4
5
6
7
8
9
10
11
jqXHR.always(function() {
    alert('JSON IS COMLETE');
});

jqXHR.done(function(data) {
    //do something with the returned data if success!
});

jqXHR.fail(function(jqXHR, textStatus) {
    alert('JSON FAILED : '+textStatus);
});

小提琴

你甚至可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
$("#button").on('click', Myfunc);

function Myfunc() {
    var jqXHR = runAjax();
        jqXHR.done(function(data) {
            alert($.parseJSON(data));
            $("#result").html('JSON IS DONE');
        });
}

function runAjax() {
    return $.getJSON(someURL);
}

小提琴


您可能会将运行在数据上的函数传递给my_func()

1
2
3
4
5
6
 //                    v--------receive a callback
function my_func(callback_fn){

    $.getJSON(someURL, callback_fn); // use the callback as the getJSON callback

}

然后…

1
2
3
my_func(function(data) {
    // do something with data
})

…或者如果您要调用的函数是一个命名函数,那么您当然会按名称传递它…

1
my_func(someOtherFunction)

不管怎样,您的my_func()函数都将使用它作为对$.getJSON调用的回调,该调用将在数据到达时调用它。