嵌套AJAX调用中的可变范围

时间:2014-06-26 17:11:28

标签: javascript ajax asynchronous jquery-deferred

我有一组自定义用户数据要进行ajax调用,如果没有用户数据,请进行另一个ajax调用以检索一组默认数据,然后执行一个函数解析数据。这是一个例子:

var oData = [],
    exampleUrl = 'example.php';
$.ajax({
    url:    exampleUrl + '?query=getUserData',
    contentType:    'application/json;odata=verbose',
    headers:        {
        'accept':   'application/json;odata=verbose'
    },
    success : function(data, request){
        // Request succeeded
        // Check the results
        if(data.length){
            // There are custom user results!
            // Parse the results
            oData = data;
        }
        else{
            // There were no custom user results...
            // Run another query to retrieve default values
            $.ajax({
                url:    examplUrl + '?query=getDefaultData',
                contentType:    'application/json;odata=verbose',
                headers:        {
                    'accept':   'application/json;odata=verbose'
                },
                success : function(data, request){
                    // Request succeeded
                    // Check the results
                    if(data.length){
                        // There was some default data!
                        // Parse the results
                        oData = data;
                    }
                    else{
                        // No data was found...
                        // Attempt to be helpful
                        console.log('No Default data was found!');
                    }
                },
                error : function(data, request){
                    // There was an error with the request
                    // Attempt to be helpful
                    console.log('Error retrieving data:');
                    console.log(data);
                    console.log(request);
                }
            });

        }
    },
    error : function(data, request){
        // There was an error with the request
        // Attempt to be helpful
        console.log('Error retrieving Custom User data:');
        console.log(data);
        console.log(request);
    },
    complete : function(){
        // Do something with the data
        index.displayData(oData);
    }
});

问题是如果第二个ajax调用运行,oData在传递给index.displayData()时根本不包含任何数据。我猜它与ajax调用的异步性质有关,但是不应该完成'追求“成功”的一切内容。运行

我也知道我可能不应该使用ajax"末日金字塔"并且应该使用承诺,但我已经尝试过并继续获得相同的结果。

感谢您的协助!

2 个答案:

答案 0 :(得分:3)

正如暴力蜡笔指出的那样,你可以试着打电话给#34;完成"你自己而不是依赖于JQuery的隐含控制流程:

function getData(exampleUrl, onComplete){
    $.ajax({
        success : function(data, request){
            if(data.length){
                onConplete(data);
            }else{
                $.ajax({
                    success : function(data, request){
                        if(data.length){
                            onComplete(data);
                        }else{
                            console.log('No Default data was found!');
                        }
                    },
                    error : function(data, request){
                        console.log('Error retrieving data:');
                    }
                });
            }
        },
        error : function(data, request){
            console.log('Error retrieving Custom User data:');
        }
    });
}

var oData = [];
getData('example.php', function(data){
    oData = data;
    index.displayData(oData);
}

BTW,请注意如何让异步函数接收自己的返回和错误回调。这有助于减少厄运问题的金字塔,而无需使用promises,也无需对返回回调进行硬编码。

答案 1 :(得分:1)

通过使用promises,您可以避免将回调传递给函数,并且通过定义实用函数可以避免重复代码。

//reusable utility function, which returns either a resolved or a rejected promise
function fetchData(queryString, cache) {
    return $.ajax({
        url: 'example.php',
        data: { query: queryString },
        type: 'JSON',//assumed
        cache: cache,
        contentType: 'application/json;odata=verbose',
        headers: { 'accept': 'application/json;odata=verbose' }
    }).then(function(data, textStatus, jqXHR) {
        if (data && data.length) {
            return data;
        } else {
            return $.Deferred().reject(jqXHR, 'no data returned').promise();//emulate a jQuery ajax failure
        }
    });
}

这允许将promise方法用于控制结构,其中包括:

  • 简明扼要
  • 使用链接,而不是嵌套
  • 提供有意义的错误消息。
//control structure
fetchData('getUserData', false).then(null, function(jqXHR, textStatus) {
    console.log('Error retrieving Custom User data: ' + textStatus);
    return fetchData('getDefaultData', true);
}).then(index.displayData, function(jqXHR, textStatus) {
    console.log('Error retrieving default data: ' + textStatus);
});

注意:

  • null中的.then(null, function(){...})允许成功回复直接转到第二个.then(index.displayData, ...)
  • 默认数据被缓存,而用户数据则没有。这不是必须使事情有效,但下次需要默认数据时会更快。
  • 在承诺的世界里,这或类似的东西是要走的路。