简体   繁体   中英

How to ensure functions in .then() complete before proceeding?

Below is the usage of $.when().then().

    $.when(setLineDet(rptId, rptLn)).then(function(data) {
        console.log("done setting line details");
        setHeaderDet(rptId);
        }).then(function(data) {
            console.log("done setting header details");
            setOtherDet();
        }).then(function(data) {
            console.log("done setting other details");
        });

Code for setLineDet():

function setLineDet(id, ln) { //set line details
    funcSel = "get_ln_det";
    var passVar = funcSel+"~@"+id+"~@"+ln;
    
    var def = new $.Deferred();
    
    ajaxCall(passVar).done(function(data) {
        var lnData = data.trim().split("~@");
        
        $("#lnDesc").val(lnData[2]);
        $("#lnDesc2").val(lnData[3]);
        $("#lnDesc3").val(lnData[4]);
        $("#lnDesc4").val(lnData[5]);
        $("#lnDesc5").val(lnData[6]);
        $("#lnDesc6").val(lnData[7]);
        $("#lnDesc7").val(lnData[8]);
        $("#lnDesc8").val(lnData[9]);
        $("#lnDesc9").val(lnData[10]);
        $("#lnDesc10").val(lnData[11]);
        $("#lnDesc11").val(lnData[12]);
        
        $.when(setRptLnList(lnData[0])).done(function(data) {
            def.resolve("done");
        });
    });
    
    return def.promise();
}

Code for setHeaderDet():

function setHeaderDet(id) { //set header details
    console.log("header 1");
    
    funcSel = "get_hdr_det";
    var passVar = funcSel+"~@"+id;
    
    var def = new $.Deferred();
    
    ajaxCall(passVar).done(function(data) {
        console.log("header 2");
        var hdrData = data.trim().split("~@");
        
        $("#hdr").val(hdrData[2]);
        $("#hdr2").val(hdrData[3]);
        $("#hdr3").val(hdrData[4]);
        $("#hdr4").val(hdrData[5]);
        $("#hdr5").val(hdrData[6]);
        $("#hdr6").val(hdrData[7]);
        $("#hdr7").val(hdrData[8]);
        $("#hdr8").val(hdrData[9]);
        $("#hdr9").val(hdrData[10]);
        $("#hdr10").val(hdrData[11]);
        
        var hasValue = 0;
        var doneSetOpr = 0;
        
        for(var i=6; i<12; i++) {
            if(hdrData[i]!="") { hasValue++; }
        }
        
        if(hdrData[6]!=""){
            $.when(setDesc("desc1", hdrData[6])).done(function(data) {
                console.log("set desc1");
                doneSetOpr++;
            });
        }
        if(hdrData[7]!=""){
            $.when(setDesc("desc2", hdrData[7])).done(function(data) {
                console.log("set desc2");
                doneSetOpr++;
            });
        }
        if(hdrData[8]!=""){
            $.when(setDesc("desc3", hdrData[8])).done(function(data) {
                console.log("set desc3");
                doneSetOpr++;
            });
        }
        if(hdrData[9]!=""){
            $.when(setDesc("desc4", hdrData[9])).done(function(data) {
                console.log("set desc4");
                doneSetOpr++;
            });
        }
        if(hdrData[10]!=""){
            $.when(setDesc("desc5", hdrData[10])).done(function(data) {
                console.log("set desc5");
                doneSetOpr++;
            });
        }
        if(hdrData[11]!=""){
            $.when(setDesc("desc6", hdrData[11])).done(function(data) {
                console.log("set desc6");
                doneSetOpr++;
            });
        }
        
        console.log("header 3");
        console.log("hasValue: "+hasValue+", doneSetOpr: "+doneSetOpr);
        
        if(doneSetOpr==hasValue && hasValue>0) {
            console.log("doneSetOpr==hasValue");
            def.resolve("done");
        }
    });
    
    console.log("header 4");
    return def.promise();
}

Code for ajaxCall():

function ajaxCall(passValues) {
    return $.ajax({
        type: "POST",
        url: "processes.jsp",
        data: {passValues: passValues}
    });
}

Console output:

line 1
line 4
line 2
line 3
done setting line details
header 1
header 4
done setting header details
done setting other details
header 2
header 3
hasValue: 3, doneSetOpr: 0
set desc1
set desc2
set desc3
  1. As you can see, the setLineDet function was completed and only then it moved to setHeaderDet. However, it did not complete the setHeaderDet function and moved right away to setOtherDet. I'm really not sure why since I'm using the same method (creating $.Deferred, .resolve(), .promise()) for all functions.

  2. Also, i could not figure out why the doneSetOpr value did not increase. Since the value isn't equal to hasValue, the.resolve() was not executed. So i tried removing the if statement and just placing.resolve(). It still resulted in the same output.

ps My program works just fine. Meaning there are no errors, and in the end all values are set accurately and pose no fatal problems. I simply would really like to understand the proper method of using promises and deferred since i may be using it wrong, since subsequent.then() are not completing the function within before proceeding to the next. Thank you.

Key Point:

  1. You only have to return the promise that was already created in the beginning and follow up by returning the promise in.then(). Rather than creating deferred objects, which ultimately results in a deferred anti-pattern.
  2. Read up and view the examples of deferred anti-pattern in the link by @Bergi.
$.when(setLineDet(rptId, rptLn)).then(function(data) {
    console.log("done setting line details");
    return setHeaderDet(rptId);
    }).then(function(data) {
        console.log("done setting header details");
        return setOtherDet();
        }).then(function(data) {
            console.log("done setting other details");
        });

Code for setLineDet():

function setLineDet(id, ln) {
    console.log("line 1");

    funcSel = "get_ln_det";
    var passVar = funcSel+"~@"+id+"~@"+ln;
    
    return ajaxCall(passVar).done(function(data) {
        console.log("line 2");
        var lnData = data.trim().split("~@");
        
        // set line values
        
        return lnData[0];
    }).then(function(data) {
        console.log("line 3");
        return setRptLnList(data);
    });
}

Code for setHeaderDet():

function setHeaderDet(id) {
    console.log("header 1");
    
    funcSel = "get_hdr_det";
    var passVar = funcSel+"~@"+id;
    
    var hdrDataCpy = ""
    
    return ajaxCall(passVar).then(function(data) {
        console.log("header 2");
        var hdrData = data.trim().split("~@");
        hdrDataCpy = hdrData;
        
        //set header values
        
        return hdrData;
    }).then(function(data) {
        console.log("header 3");
        return $.when(setDesc("desc1", hdrDataCpy[6])).then(function(data) {
            return setDesc("desc2", hdrDataCpy[7]);
        }).then(function(data) {
            return setDesc("desc3", hdrDataCpy[8]);
        }).then(function(data) {
            return setDesc("desc4", hdrDataCpy[9]);
        }).then(function(data) {
            return setDesc("desc5", hdrDataCpy[10]);
        }).then(function(data) {
            return setDesc("desc6", hdrDataCpy[11]);
        });
    });
}

Console output:

line 1
line 2
line 3
done setting line details
header 1
header 2
header 3
set desc1
set desc2
set desc3
done setting header details
done setting other details

//the "set desc1/2/3" is displayed from the setDesc() function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM