3

I am trying to create a javascript object for the following scenario

A survey interviews multiple people about food they have consumed over several meals. The object needs to be nested as follows:-

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

I am achieving that through the following codes

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

        }
    })
}

Problem is that I would like to perform some calculation once all the food consumed by each interviewer has been compiled. How do I create deferred statement to address that.

5
  • Why aren't you using fetch? You really should avoid the jquery ajax call if possible so you can easily chain your promises developer.mozilla.org/en-US/docs/Web/API/Fetch_API | developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch Commented Jun 21, 2018 at 18:50
  • 1
    your question is not clear Commented Jun 23, 2018 at 9:26
  • Robert, I have now modified the php code so that there is no need for looping in the ajax. In the example I provided how do I make the call using fetch instead of ajax. Commented Jun 24, 2018 at 18:32
  • Using a global thiscase variable like that is not safe if you try to get multiple cases in parallel Commented Jun 26, 2018 at 0:39
  • check this out > api.jquery.com/jquery.when Commented Jun 26, 2018 at 1:07

4 Answers 4

6
+25

As of jQuery 1.5 $.ajax() returns a jqXHR implementing the Promise interface.

That means you can use it in combinaison with Promise.all() ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all )

Something like this should work:

Promise.all([
    $.ajax({
        url: "a.php"
    }),
    $.ajax({
        url: "b.php"
    }),
    $.ajax({
        url: "c.php"
    }),
]).then(function() {
    // the 3 $ajax() call are finished
})
Sign up to request clarification or add additional context in comments.

Comments

2

Above all answers are great and going to solve your problem. But calling multiple ajax calls is going to hurt performance of the site. If your not using third party API and if API is in your control, then you should change the API and make it more flexible. API should be designed in way that, you can query it with number of parameters and it will return the result in single request. E.g. in above case you can pass all the ids in single request and get the data for all of them. OR in best case scenario you just ask for case and it will return all the information you need (interview, meals and food). It will be the API's responsibility to query the data in the form you need.

1 Comment

Adding to @Rahul Raut suggestion you can use api call batching for clubbing multiple ajax calls to single call. Read github.com/mlmorg/jquery.batch for more understanding.
1

Use promises to return values from your intermediate steps, and use Promise.all to combine them:

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

Comments

0

Both answers here are good, but the problem is that the Promise interface is available only in ES6. There are two possible scenarios.

  1. Use polyfill -> https://www.npmjs.com/package/promise-polyfill
  2. Use jQuery.when(). Lets assume that you created an array of all promises of requests to getfoodinmeal. Then you need to wait for all of them, so use this form $.when.apply($.when, promises).then(/* all food is now loaded*/);. I used this twice and it worked very well. I prefer this way because I do not need to load additional code.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.