解决QueryTask执行中的网络请求错误
前两天有人提到在Flex API中执行QueryTask,参数给定的情况下,excute()方法时而跳入onResult,时而跳入onFault方法中。 代码和服务环境均没有变化,通过监听HTTP请求,发现URL的参数顺序竟然会随机变化。例如,框选时设定query.outSpatialReference=map.SpatialReference, url中就会多一个这样的参数outSr=4326,但是这个参数跟其他参数的在url中的顺序不是每次都一样,我们其他的参数还有outFields,returnGeometry,geometry,f(f=json);当这个outSr=4326在url最后就不会报错,当它在最前面的时候就会报错,比如说http://192.168.10.223:8399/arcgis/rest/services/nongkeyuanedit/MapServer/0/query?geometryType=esriGeometryEnvelope&geometry="左下角的经纬度与右上角的经纬度"&f=json&outFields="输出内容"&returnGeometry=true&spatialRel=esriSpatialRelIntersects&outSr=4326。
姑且不谈ArcGIS Server段是否为Bug,同样的参数为什么会在同参数情况下出现参数顺序错误?带着疑问,打开QueryTask的源代码:
1 public function execute(query:Query, responder:IResponder = null) : AsyncToken
2 {
3 var asyncToken:AsyncToken;
4 var query:* = query;
5 var responder:* = responder;
6 var generateUrlVariables:* = function (geometry:Geometry = null) : void
7 {
8 var _loc_3:JSONEncoder = null;
9 var _loc_2:* = new URLVariables();
10 _loc_2.f = useAMF ? ("amf") : ("json");
11 _loc_2.returnGeometry = query.returnGeometry;
12 if (geometry)
13 {
14 _loc_3 = new JSONEncoder(null);
15 _loc_2.geometryType = geometry.type;
16 if (geometry.spatialReference)
17 {
18 _loc_2.inSR = geometry.spatialReference.toSR();
19 }
20 _loc_2.geometry = _loc_3.convertToString(geometry, false);
21 }
22 if (query.spatialRelationship)
23 {
24 _loc_2.spatialRel = query.spatialRelationship;
25 }
26 if (query.text)
27 {
28 _loc_2.text = query.text;
29 }
30 if (query.where)
31 {
32 _loc_2.where = query.where;
33 }
34 if (query.outSpatialReference)
35 {
36 _loc_2.outSR = query.outSpatialReference.toSR();
37 }
38 if (query.outFields)
39 {
40 _loc_2.outFields = query.outFields.join();
41 }
42 if (query.objectIds)
43 {
44 _loc_2.objectIds = query.objectIds.join();
45 }
46 if (query.relationParam)
47 {
48 }
49 if (query.spatialRelationship == Query.SPATIAL_REL_RELATION)
50 {
51 _loc_2.relationParam = query.relationParam;
52 }
53 if (query.timeExtent)
54 {
55 _loc_2.time = query.timeExtent.toTimeParam();
56 }
57 if (!isNaN(query.maxAllowableOffset))
58 {
59 _loc_2.maxAllowableOffset = query.maxAllowableOffset;
60 }
61 asyncToken = sendURLVariables2("/query", _loc_2, handleExecute, asyncToken);
62 return;
63 }// end function
64 ;
65 if (query == null)
66 {
67 if (Log.isWarn())
68 {
69 logger.warn("{0}::execute::a query was not defined", id);
70 }
71 return null;
72 }
73 if (Log.isDebug())
74 {
75 logger.debug("{0}::execute:{1}", id, query);
76 }
77 asyncToken = new AsyncToken(null);
78 if (responder)
79 {
80 asyncToken.addResponder(responder);
81 }
82 if (query.geometry)
83 {
84 if (autoNormalize)
85 {
86 var getNormalizedGeometryFunction:* = function (item:Object, token:Object = null) : void
87 {
88 generateUrlVariables((item as Array)[0] as Geometry);
89 return;
90 }// end function
91 ;
92 var faultHandler:* = function (fault:Fault, asyncToken:AsyncToken) : void
93 {
94 var _loc_3:IResponder = null;
95 for each (_loc_3 in asyncToken.responders)
96 {
97
98 _loc_3.fault(fault);
99 }
100 dispatchEvent(new FaultEvent(FaultEvent.FAULT, false, false, fault));
101 return;
102 }// end function
103 ;
104 GeometryUtil.normalizeCentralMeridian([query.geometry], GeometryServiceSingleton.instance, new AsyncResponder(getNormalizedGeometryFunction, faultHandler, asyncToken));
105 }
106 else
107 {
108 this.generateUrlVariables(query.geometry);
109 }
110 }
111 else
112 {
113 this.generateUrlVariables();
114 }
115 return asyncToken;
116 }// end function
问题就处在generateUrlVariables方法上,其中_loc_2为URLVariables对象,是在HTTP请求中要构建的请求主体对象。参数作为其内部属性存在,对象的属性添加是有顺序的,在stack中会按顺序添加,但在解析时通过什么方法去的每个变量并拼成URL,属于Flex框架问题。暂时的解决办法只能是拼凑URL成可接受格式。