【问题标题】:Using jQuery Deferred with multiple ajax containing $.each将 jQuery Deferred 与包含 $.each 的多个 ajax 一起使用
【发布时间】:2018-06-19 17:45:11
【问题描述】:

我正在尝试为以下场景创建一个 javascript 对象

一项调查采访了多人,了解他们在几餐中食用的食物。对象需要嵌套如下:-

case={}
case[x].Interview={}
case[x].Interview[y].meals={}
case[x].Interview[y].meals[z].Food=[]

我正在通过以下代码实现这一目标

var $caseoffset=0
loadcases()
function loadcases() {
    $.ajax({
        url: "functions.php",data: {offset: $caseoffset,method: "getCase"},method: "post",dataType: 'json',
        success: function(result) {
            cases = result;
            loadinterview(cases[$caseoffset].fldCaseID)         
        }
    })  
}

function loadinterview($CaseID) {
    $.ajax({
        url: "functions.php",
        data: {method: "getinterview",caseid: $CaseID}, method: "post",dataType: 'json',
        success: function(result) {
            thiscase=cases[$caseoffset]
            thiscase.interviewcount=result.length
            thiscase.interviews={}

            $.each(result,function(key,val){
                thiscase.interviews[val.fldInterviewID]=val
                loadmeals(val.fldInterviewID)
            })  
        }    
    })
}
function loadmeals($InterviewID) {
    $.ajax({
        url: "functions.php",
        data: {method: "getmeal",InterviewID: $InterviewID},method: "post",dataType: 'json',
        success: function(result) {
            thiscase.interviews[parseInt($InterviewID)].mealcount = result.length
            thiscase.interviews[parseInt($InterviewID)].meals={}

            $.each(result, function(key, val) {

                thiscase.interviews[parseInt($InterviewID)].meals[parseInt(val.fldMealHistoryID)] = val
                getfoodinmeal($InterviewID, val.fldMealHistoryID)
            })
        }
    })
}

function getfoodinmeal($interviewid, $mealid) {
    $.ajax({
        url: "functions.php",data: {method: "getfoodinmeal",mealid: $mealid},
        method: "post",

        dataType: 'json',

        success: function(result){
            foodinmeal = [];

            $.each(result, function(key, val) {
                foodinmeal.push(val.fldFoodID)
            })

            thiscase.interviews[$interviewid].meals[$mealid].food = foodinmeal

        }
    })
}

问题是我想在每个面试官消耗的所有食物都编译后进行一些计算。我如何创建延期声明来解决这个问题。

【问题讨论】:

标签: javascript jquery jquery-deferred


【解决方案1】:

从 jQuery 1.5 开始,$.ajax() 返回一个实现 Promise 接口的 jqXHR

这意味着您可以将它与Promise.all() (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) 结合使用

这样的事情应该可以工作:

Promise.all([
    $.ajax({
        url: "a.php"
    }),
    $.ajax({
        url: "b.php"
    }),
    $.ajax({
        url: "c.php"
    }),
]).then(function() {
    // the 3 $ajax() call are finished
})

【讨论】:

    【解决方案2】:

    首先,所有答案都很棒,可以解决您的问题。但是调用多个 ajax 调用会损害网站的性能。如果您不使用第三方 API 并且 API 在您的控制之下,那么您应该更改 API 并使其更灵活。 API 的设计方式应该是,您可以使用多个参数查询它,它将在单个请求中返回结果。例如。在上述情况下,您可以在单个请求中传递所有 id 并获取所有这些 id 的数据。或者在最好的情况下,您只需询问案例,它就会返回您需要的所有信息(面试、膳食和食物)。 API 将负责以您需要的形式查询数据。

    【讨论】:

    • 添加到@Rahul Raut 的建议中,您可以使用 api 调用批处理将多个 ajax 调用合并到单个调用。阅读github.com/mlmorg/jquery.batch 了解更多。
    【解决方案3】:

    使用 promise 从中间步骤返回值,并使用 Promise.all 组合它们:

    function loadcase(offset) {
        return $.ajax({
            url: "functions.php",
            data: {method: "getCase", offset: offset},
            method: "post", dataType: 'json',
        }).then(function(cases) {
            return loadinterview(cases[$caseoffset]);
        })
    }
    
    function loadinterview(thiscase) {
        $.ajax({
            url: "functions.php",
            data: {method: "getinterview", caseid: thiscase.fldCaseID},
            method: "post", dataType: 'json'
        }).then(function(result) {
            thiscase.interviewcount=result.length
            thiscase.interviews={}
    
            var promises = $.map(result,function(key,val){
                thiscase.interviews[val.fldInterviewID]=val
                return loadmeals(val);
            })
    
            return Promise.all(promises).then(function() {
                return thiscase;
            });
        });
    }
    function loadmeals(thisinterview) {
        $.ajax({
            url: "functions.php",
            data: {method: "getmeal", InterviewID: thisinterview.fldInterviewID},
            method: "post", dataType: 'json'
        }).then(function(result) {
            thisinterview.mealcount = result.length
            thisinterview.meals={}
    
            var promises = $.map(result, function(key, val) {
                thisinterview.meals[val.fldMealHistoryID] = val
                return getfoodinmeal(val);
            })
            return Promise.all(promises).then(function() {
                return thisinterview;
            });
        })
    }
    
    function getfoodinmeal(thismeal) {
        $.ajax({
            url: "functions.php",
            data: {method: "getfoodinmeal", mealid: thismeal.fldMealHistoryID},
            method: "post", dataType: 'json',
        }).then(function(result) {
            thismeal.food = $.map(result, function(key, val) {
                return val.fldFoodID;
            })l
            return thismeal;
        })
    }
    
    loadcase(0).then(function(case) {
        // everything is loaded
        console.log(case);
    })
    

    【讨论】:

      【解决方案4】:

      这里的两个答案都很好,但问题是 Promise 接口仅在 ES6 中可用。有两种可能的情况。

      1. 使用 polyfill -> https://www.npmjs.com/package/promise-polyfill
      2. 使用jQuery.when()。让我们假设您创建了一个包含所有对getfoodinmeal 的请求的承诺的数组。然后您需要等待所有这些,因此请使用此表单$.when.apply($.when, promises).then(/* all food is now loaded*/);。我用了两次,效果很好。我更喜欢这种方式,因为我不需要加载额外的代码。

      【讨论】:

        猜你喜欢
        • 2019-01-10
        • 2015-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-27
        • 1970-01-01
        • 1970-01-01
        • 2016-01-08
        相关资源
        最近更新 更多