如何解决jQuery Promise的.then()在AJAX执行完成前触发的问题
问题根源
你的代码存在两层异步操作,仅对第一层$.ajax请求做了Promise封装,没有处理第二层的图层查询异步逻辑:retrieveTrees函数内部的userLayer.query().where().run()是异步回调方法,retrieveTrees不会等待回调执行完成,就会直接返回userLayer对象。此时你在外层Promise的success回调里直接resolve(retrieveTrees(response)),会导致.then()触发时,run回调里的userLayer.addTo(map)逻辑还没有执行,自然打印的map.hasLayer(userLayer)为false。
修复方案
1. 改造retrieveTrees函数,使其返回Promise
将图层查询和添加的逻辑也封装进Promise,等图层成功添加到地图后再resolve:
function retrieveTrees(response) { return new Promise((resolve, reject) => { let conditionalVal = " or "; let treeID = ""; for(let i=0; i<response.length; i++) { treeID = response[i]['MYTreeID'] if(i==0) { all_trees = `${IMP_FIELDS.TREEMAIL_SEARCH} like '%${treeID}%'`; } else { all_trees += conditionalVal + `${IMP_FIELDS.TREEMAIL_SEARCH} like '%${treeID}%'`; } } console.log("所有树ID",all_trees); queryString = all_trees + ` and Actual_Tree_Type like '%${featureType}%'`; let layerOptions = $.extend( { where: queryString }, userPlottedLayerView18Options ); layerOptions.url = mapLayers.userPlantedLayer; userLayer = L.esri.featureLayer(layerOptions); userLayer .query() .where(queryString) .run((err, featureCollection, response) => { if (err) { return reject(err); } if (featureCollection.features.length > 0) { removeClass($loadingDiv, 'show'); //将userLayer添加到地图上 userLayer.addTo(map); console.log(map.hasLayer(userLayer), "AJAX内部检查") } // 操作完成后resolve,把userLayer传出去 resolve(userLayer); }); }) }
2. 调整外层Promise的resolve逻辑
因为retrieveTrees现在返回Promise,直接把它作为resolve的参数即可,Promise会自动等待内部异步完成后再触发外层的.then():
return new Promise(function(resolve, reject){ $.ajax({ url: "../apis/treemailSearch", method: 'GET', dataType: 'json', data : configData, contentType: 'application/json', success: response => { // 直接resolve retriveTrees返回的Promise resolve(retrieveTrees(response)); }, error : function(err){ reject(err, "此处打印错误"); } }); })
3. 修正调用处的userLayer赋值逻辑
你原来的代码把addUserLayerTreemail返回的Promise赋值给了userLayer,这是错误的,需要在.then()回调里接收返回的图层对象:
// 不要直接把Promise赋值给userLayer this.addUserLayerTreemail( $loadingContent, $loadingDiv, treeLayers, map, heritage_cluster_layer_view_18, flowering_cluster_layer_view_18, IMP_FIELDS, suggestion, userPlottedLayerView18Options, userLayer, $speciesError ).then( function(userLayer){ // 在这里接收返回的图层对象 console.log(map.hasLayer(userLayer), "检查图层是否存在") setSearchState(true); $mapSearch.blur(); }).catch(function(err){ console.log("捕获到错误", err) });
内容的提问来源于stack exchange,提问作者Ian Bell
相关产品推荐
相关产品推荐

