删除ObservableArray Aync呼叫绑定顺序问题



我有一个observablearray。使用ajax async调用我正在获取数据以进行绑定。有1000个数据。在每个呼叫中,将获取100个数据。问题是由于AJAX异步呼叫订单不会来自1-1000。由于浏览器不会响应,因此无法作为同步调用。如何将异步数据分类为"敲除"?

var DataVM = ko.observableArray([]);
ko.applyBindings(DataVM, document.getElementById("ControlBlock"));
for (var i = 0; i < totalAjaxCall; i++) {
                        GetData(guid, start, end, self.DataCallback);
                        start = start + 100;
                        end = end +100;
                    }
 DataCallback= function (result) {
        var temp = JSON.parse(result.d); 
        var data = [];
        var data = temp.Data;
        for (var j = 0; j < data.length; j++) {
            var tempItem_ = new Item();
            tempItem_.Number = data[j].Number;
        // Other codes           
            DataVM.push(tempItem_ );
        }
    };

您可以记住它们进入时的块,然后在收到全部的情况下重新组装东西。请参阅评论:

var DataVM = ko.observableArray([]);
ko.applyBindings(DataVM, document.getElementById("ControlBlock"));
// Remember the results in a temporary array of arrays
var received = 0;
var receivedBlocks = [];
for (var i = 0; i < totalAjaxCall; i++) {
    // Tell `DataCallback` which block it's going to get
    GetData(guid, start, end, self.DataCallback.bind(null, i));
    // No need for `self` ----^^^^^
    start = start + 100;
    end = end +100;
}
DataCallback = function (i, result) {
    // Create and remember the items for this block
    receivedBlocks[i] = JSON.parse(result.d).map(function(e) {
        var tempItem_ = new Item();
        tempItem_.Number = num;
        return tempItem_;
    });
    ++received;
    // Do we have them all?
    if (received == totalAjaxCall) {
        // Flatten our array of arrays, now we have all the pieces
        var receivedItems = []
        receivedBlocks.forEach(function(block) {
            receivedItems.push.apply(result, block);
        });
        // Push all of those onto DataVM as a single operation
        // Note: You were using `DataVM.push`, so I used that here,
        // but if you wanted to *replace* the contents of `DataVM`,
        // (or if you know it's empty), you'd just do:
        //      DataVM(receivedItems);
        // instead.
        DataVM.push.apply(DataVM, receivedItems);
    }
};

我不确定您要偏离当前代码多远,但我想宣传淘汰赛的一些其他功能:)

如果您为请求创建一个小的"中间"模型,则可以使用computed值自动跟踪正确排序的数据列表。

例如,如果您像这样定义了new Request()

var Request = function(start, end) {
  this.completed = ko.observable(false);
  this.data = [];
  getData(start, end, this.onLoad.bind(this));
};
Request.prototype.onLoad = function(data) {
  this.data = data;
  this.completed(true);
};

您可以更改for循环以创建"中间"模型。这为0创建Request100101201等。这些模型中的每一个都以创建的顺序存储在数组中。

function getDataRequests(start, end, chunkSize) {
  var requests = [];
  for (var i = start; i < end; i += chunkSize) {
    requests.push(new Request(i, Math.min(i + chunkSize, end)));
  }
  return requests;
};

现在您可以创建一个有序的数组,可以通过将所有completed请求合并在一起来计算data的另一个有序数组:

var DataVM = function(start, end, chunkSize) {
  // We keep track of a list of requests
  var requests = ko.observableArray(
    getDataRequests(start, end, chunkSize)
  );
  // Because requests have an observable completed prop,
  // we can automatically keep track of a list of completed
  // requests
  var completedRequests = ko.pureComputed(() =>
    requests().filter(r => r.completed()));
  // Now, whenever a requests completes, we flatten the 
  // `data` parts for `completed` requests
  this.data = ko.pureComputed(() => completedRequests()
    .reduce((items, r) => items.concat(r.data), []));
};

由于您具有requests数组,因此可以轻松计算UI属性。例如:firstLoaded是一个计算,它返回 first 请求的completed值。

这是一个完整的示例(ES2015):

var DataVM = function(start, end, chunkSize) {
  // We keep track of a list of requests
  var requests = ko.observableArray(
    getDataRequests(start, end, chunkSize)
  );
  // Because requests have an observable completed prop,
  // we can automatically keep track of a list of completed
  // requests
  var completedRequests = ko.pureComputed(() =>
                                          requests().filter(r => r.completed()));
  // Now, whenever a requests completes, we flatten the 
  // `data` parts for `completed` requests
  this.data = ko.pureComputed(() => completedRequests()
                              .reduce((items, r) => items.concat(r.data), []));
  // Shows progress
  this.loadingMsg = ko.pureComputed(() => {
    var completedCount = completedRequests().length,
      	allCount = requests().length;
    return completedCount === allCount 
    	? `Done loading ${end - start} items in ${allCount} steps` 
      : `Loading... (${completedCount}/${allCount})`;
  });
  // Check if the first (if any) request has completed loading
  this.firstCompleted = ko.pureComputed(() =>
    requests().length && requests()[0].completed());
};
var Request = function(start, end) {
  this.completed = ko.observable(false);
  this.data = [];
  getData(start, end, this.onLoad.bind(this));
};
Request.prototype.onLoad = function(data) {
  this.data = data;
  this.completed(true);
};
var vm = new DataVM(0, 50, 5);
ko.applyBindings(vm);
// Mock async ajax stuff and data getters
function getDataRequests(start, end, chunkSize) {
  var requests = [];
  for (var i = start; i < end; i += chunkSize) {
    requests.push(new Request(i, Math.min(i + chunkSize, end)));
  }
  return requests;
};
function getData(start, end, cb) {
  setTimeout(function() {
  	cb(mockData(start, end));
  }, Math.random() * 3000 + 500);
}
function mockData(from, to) {
	return Array(to - from).fill(from).map(function(_, i) {
      return from + i;
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="text: loadingMsg"></div>
<ul data-bind="foreach: data, visible: firstCompleted" style="border: 1px solid black;">
  <li data-bind="text: $data"></li>
</ul>

最新更新