我正在使用ESRI Javascript API检索ArcGIS Server中数据集中的所有记录以进行客户端处理。服务器将每个响应限制为1000条记录。这意味着我必须在检索时跟踪我的功能,然后检索下一批。对检索记录的API的调用返回dojo/Deferred
对象。
我希望能够检索一批1000条记录,处理它们,并将它们按顺序保存回数据集。同时,只要从数据集中检索到一批记录,就会开始检索下一批记录。
我已经使用递归函数调用做了类似的事情,并将生成的dojo/Deferred
保存到列表中,以便稍后使用dojo/promise/all
进行处理。但是,这意味着在检索完所有功能后立即处理这些功能。我宁愿能够在检索每个批次时单独处理它们。
我的应用程序使用dojo
与ESRI API和jQuery / jQuery Mobile。
以下是我的代码,它会立即返回所有功能:
//layer = dataset (geographic data)
//count = count of records (features) in dataset
//objectIds = list of all unique record ID's in dataset. This can be retrieved from the server and is not limited by the 1000 record limit
//Query = ESRI API Query Task used to retrieve features from the dataset
if (count > layer.maxRecordCount) {
var features = [];
var i = 0;
var deferreds = [];
for (i; i < objectIds.length; i += layer.maxRecordCount) {
var q = new Query();
q.objectIds = objectIds.slice(i, i + layer.maxRecordCount);
var deferred;
if (select) { deferred = layer.selectFeatures(q, selectionType); }
else { deferred = layer.queryFeatures(q); }
deferreds.push(deferred);
}
var deferred = all(deferreds).then(function(featuresets) {
var featureLists = array.map(featuresets, function(featureset) {
return featureset.features || featureset;
});
var features = [].concat.apply([], featureLists);
return features;
});
return deferred;
}
更新
我已经找到了一种方法,可以使用Array
作为queue
来实现我想要的目标。
以下是从数据库中检索记录的功能:
getAllFeatures : function(layer, returnGeometry, fields) {
var queue = ["start"];
var q = new esriQuery();
q.where = "1=1";
var qt = new QueryTask(layer.url);
layer.queryIds(q).then(function(objectIds) {
var deferreds = [];
for (var i = 0; i < objectIds.length; i += layer.maxRecordCount) {
var q = new esriQuery();
q.objectIds = objectIds.slice(i, i + layer.maxRecordCount);
q.returnGeometry = !!returnGeometry;
q.outFields = fields && [layer.objectIdField].concat(fields) || ["*"];
deferreds.push(qt.execute(q).then(function(featureSet) {
queue.push(featureSet.features);
}));
}
all(deferreds).then(function() {
queue.push("stop");
});
});
return queue;
}
以下是处理数据的代码:
var queue = pgUtils.getAllFeatures(layer, false, [priorityField.name]);
var features = queue.shift();
var interval;
if (features === "start") {
interval = setInterval(function() {
features = queue.shift();
if (features && features instanceof Array) {
self._prioritize(features, formData);
new esriRequest({
url : layer.url + "/applyEdits",
content : {
f : "json",
updates : JSON.stringify(features)
}
}, {usePost : true});
} else if (features === "stop") {
clearInterval(interval);
}
}, 500);
}
正如您所看到的,我使用名为Array
的{{1}}推送queue
函数中的各个回复,并使用getAllFeatures
从{{1}检索这些回复直到setInterval
信号被找到。到目前为止,这似乎与我的450条记录的测试数据集一起使用。我不确定这对于更大的数据集是如何工作的。我绝对愿意接受任何有关更好方法的建议。
答案 0 :(得分:0)
查看DeferredList。
var def_array = [];
for(..) {
var def = new Deferred();
...
def_array.push(def);
}
new DeferredList(def_array).then(function(res){
...
//this runs only all the deferreds in the def_array is invoked and completed
});
DeferredList具有许多其他参数/标志,这些参数/标志用于特定目的,基于要求。但是,对于你的情况,我猜,上面的解决方案就足够了。
答案 1 :(得分:0)
如果我正确地解释你的问题,你基本上要串行而不是并行地请求批处理,在请求下一个之前处理每个批处理。正如您所指出的那样,all
确实有助于并行处理。你需要一种不同的方法来做你想做的事情(注意我无法测试这个,所以它可能仍然需要一些工作):
var i = 0,
len = objectIds.length,
features = [];
function requestNext() {
var q = new Query(),
promise;
q.objectIds = objectIds.slice(i, i + layer.maxRecordCount);
promise = select ? layer.selectFeatures(q, selectionType) :
layer.queryFeatures(q);
return promise.then(function (featureset) {
// Add the latest set of results to the features array
features = features.concat(featureset.features || featureset);
// If there are more objects to query, call this function again,
// chaining the subsequent request's resolution to this promise;
// otherwise, return the built features array
i += layer.maxRecordCount;
return i < len ? requestNext() : features;
});
}
return requestNext();