jQuery .then()无法正常工作

时间:2018-07-14 11:19:44

标签: javascript jquery promise internet-explorer-11

我正在使用jQuery(v3.3.1-min)承诺将某些函数调用链接在一起,因为它们相互依赖。 在大多数情况下,排序工作正常,但对于某些嵌套调用,它不等待上一个函数完成并跳转到下一行代码。稍后会恢复到原来的状态,但是由于此时HTML表已经准备好,所以此时无法使用这些值。

我将在这里尝试解释一些代码示例。

初始化代码[行号360/61/62]:

GetUpstreamTrace(classID, selectedFeatOID, minSeqNo, maxSeqNo).then(function () {//line#360
    GetConnectedTrace().then(function () { //line#361
       PopulateTraceTable(); //line#362
    });
});

GetUpstreamTrace()中,我调用了其他几种方法,其中一些是XHR,其余的是常规方法。 XHR似乎每次都兑现诺言,因为它在 onreadystatechange 块内得到了已解决

行为异常的代码[line#:527-596]:

$.each(queryResultJson.features, function (indx, queryFeat) {//line#527
        //fetch values
        console.log("  Inside $.each() [line# 499], index=" + indx);
        connectorClassId = parseInt(queryFeat.attributes["CONNECTOR_CLASSID"]);
        connectorObjectId = parseInt(queryFeat.attributes["CONNECTOR_OBJECTID"]);
        toObjId = parseInt(queryFeat.attributes["TO_OBJECTID"]);
        toClsId = parseInt(queryFeat.attributes["TO_CLASSID"]);
        fromObjId = parseInt(queryFeat.attributes["FROM_OBJECTID"]);
        fromClsId = parseInt(queryFeat.attributes["FROM_CLASSID"]);
        toFirstUnit = parseInt(queryFeat.attributes["TO_FIRSTUNIT"]);
        fromFirstUnit = parseInt(queryFeat.attributes["FROM_FIRSTUNIT"]);
        numberOfUnits = parseInt(queryFeat.attributes["NUMBER_OF_UNITS"]);

        if ((minSeqNo >= toFirstUnit && minSeqNo < (toFirstUnit + numberOfUnits)) || (toFirstUnit >= minSeqNo && toFirstUnit < (minSeqNo + maxSeqNo))) {
            if (numberOfUnits >= maxSeqNo) {
                if ((minSeqNo + maxSeqNo) > (toFirstUnit + numberOfUnits))
                    numberOfUnits = (toFirstUnit + numberOfUnits) - minSeqNo;
                else
                    numberOfUnits = maxSeqNo;

                fromFirstUnit = (minSeqNo - toFirstUnit) + fromFirstUnit;
                toFirstUnit = minSeqNo;
            }
            else {
                if (minSeqNo > toFirstUnit) {
                    numberOfUnits = (toFirstUnit + numberOfUnits) - minSeqNo;
                    fromFirstUnit = (minSeqNo - toFirstUnit) + fromFirstUnit;
                    toFirstUnit = minSeqNo;
                }
            }
            //line# 558
            GetConnectedInfo(selectedFeatOID, classID, minSeqNo, maxSeqNo, toObjId, toClsId, toFirstUnit, numberOfUnits, fromObjId, fromClsId, fromFirstUnit).then(function (connectedInfoResult) {
                connectionInfo += connectedInfoResult;
                //console.log("  After GetConnectedInfo [line# 530]...");
                //console.log("  connectionInfo [line# 492]: " + connectedInfoResult);
                objTable += '{' +
                                '"OBJECTID" : "' + fromObjId + '", ' +
                                '"OBJ_CLASSID" : "' + fromClsId + '", ' +
                                '"FROM_FIRSTUNIT" : "' + toFirstUnit + '", ' +
                                '"TO_FIRSTUNIT" : "' + fromFirstUnit + '", ' +
                                '"NO_OF_UNIT" : "' + numberOfUnits + '"' +
                            '},';
                //console.log("  objTable [line# 533]: " + objTable);
                totalUnitCount += numberOfUnits;
            });

            //});
        }
    });

    //line# 578
    var objTableJson = '', tmpObjTable = '';
    if (objTable.length > 0) {
        tmpObjTable = objTable;
        tmpObjTable = tmpObjTable.slice(0, tmpObjTable.lastIndexOf(','));
        tmpObjTable = '[' + tmpObjTable + ']';

        objTableJson = JSON.parse(tmpObjTable);
    }
    //console.log("  tmpObjTable [line# 548]: " + tmpObjTable);
    if (objTableJson.length == 0) {
        if (checkConnected == true) {
            GetConnectedInfo(selectedFeatOID, classID, minSeqNo, maxSeqNo, selectedFeatOID, classID, minSeqNo, maxSeqNo, 0, 0, 0).then(function (connectedInfoResult) {
                connectionInfo += connectedInfoResult;//line#: 590
                totalUnitCount = numberOfUnits;
                console.log("  After GetConnectedInfo [line# 557]...");
                //console.log("  connectionInfo [line# 492]: " + connectedInfoResult);
            });
        }
    }

我得到的程序流程是这样的: 360行>> 527 >> 558 >> 361 >> 362 >> 578 >> 590 ...

我不明白为什么它不等待 GetConnectedInfo 完成并跳出线。

任何指针?

谢谢!

UJ

更新
因此,为了解释我面临的问题,我使用$ .each创建了这个简单的代码。同样的事情在这里也发生...您将注意到$ .each首先完成,然后嵌套.then。 我的理解是$ .each在.then()完成之前不会移动到下一个迭代,但是不会!还是很困惑,不确定我是否缺少一些非常基本的东西。

<!DOCTYPE HTML>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script>
        function doSomething(){
            console.log("Inside doSomething()...");

            var arr=[1,2,3,4,5,6,7,8,9,10];

            $.each(arr,function(indx,item){
                console.log(" Inside $.each - index/item: "+indx+"/"+item);

                $.when(doSomethingElse(item)).done(function(response){
                console.log("  doSomethingElse response..."+response);  [![Working demo][1]][1] 
                });                 
            });

            console.log("Back inside doSomething()!");
        }

        function doSomethingElse(intgr){
            var def=$.Deferred();

            def.resolve("  doSomethingElse"+intgr);

            return def.promise();
        }
    </script>
</head>
<body onload="doSomething()">
    <h2>jQuery Promise Test. Check console messages for details.</h2>
</body>
</html>

Output

2 个答案:

答案 0 :(得分:1)

如果您需要在继续进行之前在GetConnectedInfo()循环中完成所有each个请求,则可以创建一个包含这些承诺的数组,并可以使用Promise.all()(或{{1 }})在它们全部解决后运行

代替使用$.when()试试

each

永远不要手动创建JSON。与直接使用对象相比,它容易出错并且需要更多的工作。而不是向var feature_promises = queryResultJson.features.map(function(queryFeat, indx) { console.log(" Inside $.each() [line# 499], index=" + indx); //...... //line# 558 RETURN THE PROMISE TO MAPPED ARRAY return GetConnectedInfo( /* args */ ).then(function(connectedInfoResult) { //...... // return something }) }); Promise.all(feature_promises).then(function(results){ //line# 578 var objTableJson = '', tmpObjTable = ''; if (objTable.length > 0) { //...... )} 添加字符串,它应该是将实际对象放入其中的数组

答案 1 :(得分:0)

好,所以我终于使它起作用了,这就是方法(加上,为什么它表现得如此)。

通过jQuery 3.0升级说明,我遇到了以下内容:
Breaking change and Feature: jQuery.Deferred is now Promises/A+ compatible

  

遵守Promises / A +要求的另一个行为更改是   延迟的.then()回调始终被异步调用。   以前,如果将.then()回调添加到Deferred中,则   已经解决或被拒绝,回调将立即运行,   同步。

因为我在开发中使用的是同一个库以及此处发布的演示代码,所以我所看到的行为是实际上应该如何(并使我困惑!)。

建议使用 $。when() .done()获得旧的同步行为。

  

.done()、. fail()和.pipe()之类的延迟方法保留其   过时的行为,因此不符合Promises / A +。如果您需要   同步解析,不希望将异常转换为拒绝   值或拒绝回调返回转换为实现值的值,   或想让抛出的错误冒出来的地方冒出来,   您可以使用这些方法代替.then()和.catch()。

也在此处发布该示例的更新代码。

UJ

enter image description here