我正在使用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>
答案 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