如何产生结果Javascript嵌套缺陷

How to Yield Results Javascript Nested Deferreds

本文关键字:嵌套 缺陷 Javascript 结果 何产生      更新时间:2023-09-26

我正在使用ESRI Javascript API来检索ArcGIS服务器中数据集中的所有记录,以便进行客户端处理。服务器将每个响应限制为1000条记录。这意味着我必须在检索我的功能时跟踪它们,然后检索下一批。对检索记录的API的调用返回一个dojo/Deferred对象。

我希望能够检索一批1000条记录,处理它们,并按顺序将它们保存回数据集。同时,一旦从数据集中检索到一批记录,就会开始检索下一批。

我已经做了类似的事情,使用递归函数调用并将生成的dojo/Deferred保存到列表中,以便稍后使用dojo/promise/all进行处理。然而,这意味着在检索到所有特征后,立即处理所有特征。我更希望能够在检索每个批次时单独处理它们。

我的应用程序将dojo与ESRI API和jQuery/jQueryMobile一起使用。

这是我的代码,它一次返回所有功能:

//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);
}

如您所见,我使用名为queueArray来推送getAllFeatures函数中的各个响应,并使用setIntervalqueue检索这些响应,直到找到"stop"信号。到目前为止,这似乎适用于我的450条记录的测试数据集。我还不确定这将如何适用于更大的数据集。我绝对愿意接受任何关于更好方式的建议。

查看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有许多其他参数/标志,这些参数/标志是基于需求的特定用途。但是,对于你的情况,我想,以上的解决方案就足够了。

如果我正确解释了您的问题,那么您基本上希望以串行方式而不是并行方式请求批次,在请求下一个批次之前先处理每个批次。正如您所注意到的,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();