使用 AJAX 回调更新挖空可观察数组会生成随机排序的结果
Updating knockout observableArray with AJAX callback produces randomly sorted results
这是一些复制该问题的代码
places = ["London","Paris","Brussels"];
placeWikis = ko.observableArray([]);
var viewModel = function(){
for (i in places) {
function wikiInit(callback){
this.wikiMarkup = "";
var wikiTitle = places[i].replace(" ", "_");
var wikiURL = "https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles="+places[i];
$.ajax({
type:"GET",
dataType:"jsonp",
async: false,
url: wikiURL,
success: function(result){
callback(result.query.pages[Object.keys(result.query.pages)[0]].extract);
},
error: function(){
}
});
};
wikiInit(function (wikiString) {
var wikiMarkup = "<h4>Wikipedia:</h4>" + "<p>" + wikiString + "</p>";
placeWikis.push(wikiMarkup);
console.log(placeWikis());
});
}
ko.applyBindings(new viewModel(), view);
问题是每次此代码运行并从源(在本例中为维基百科(返回数据时,placesWikis(( 的结果都是随机排序的。我在不同的<div>
上单独添加 API 结果,所以我需要结果的索引与其各自条目的索引相同[]
您有两个订单问题:
-
for.in
不保证订单; - 您在回调中异步填充
observableArray
,但不能保证它们会到达,以便您触发它们!
后者可能是最突出的问题。您当前将结果push
到可观察数组中,但您按照浏览器返回结果的顺序执行此操作。
这是对您的问题的稍微最少的重现,其中差异回调时间被夸大了:
// Mock Ajax stuff:
var $ = {
ajax: function(options) {
// Simulate unknown return moment with setTimeout:
setTimeout(function() {
options.success(options.url + " is a great city...");
}, Math.random() * 1500 + 50);
}
}
function ViewModel() {
var self = this;
self.items = ko.observableArray([]);
var places = ["london", "brussels", "paris"];
function wikiInit(place, callback) {
$.ajax({
url: "http://en.wikipedia.org/w/" + place,
success: function(result) {
callback(result);
}
});
}
for (var i = 0; i < places.length; i++) {
wikiInit(places[i], function(wikiString) {
self.items.push(wikiString);
console.log(self.items());
});
}
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: items">
<li data-bind="text: $data"></li>
</ul>
如您所见,每次运行时,结果都有可能出现故障。
选项 1 是将新项目拼接到数组中您希望它们所在的位置(而不是使用 push
(。这是IMO有点复杂的方法,我将把代码留给读者。
选项 2,一种可能更简单的方法是事先准备数组,并在回调时填充数组。 例如像这样:
// Mock Ajax stuff:
var $ = {
ajax: function(options) {
// Simulate unknown return moment with setTimeout:
setTimeout(function() {
options.success(options.url + " is a great city...");
}, Math.random() * 1500 + 50);
}
}
function Place(data) {
this.place = data.place;
this.wikistuff = ko.observable("");
}
function ViewModel() {
var self = this;
self.items = ko.observableArray([]);
var places = ["london", "brussels", "paris"];
function wikiInit(place, callback) {
var placeVm = new Place({ place: place });
self.items.push(placeVm);
$.ajax({
url: "http://en.wikipedia.org/w/" + place,
success: function(result) {
callback(result, placeVm);
}
});
}
for (var i = 0; i < places.length; i++) {
wikiInit(places[i], function(wikiString, placeVm) {
placeVm.wikistuff(wikiString);
});
}
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: items">
<li data-bind="text: wikistuff"></li>
</ul>
此结果始终按原始数组的顺序排列。
它当前始终显示项目符号,甚至在回调完成之前。我这样做只是为了演示解决方案的工作原理,但你可以很容易地做到这一点......
<li data-bind="text: wikistuff, visible: !!wikistuff()"></li>
。如果需要。
相关文章:
- JavaScript数组排序(函数)用于对表行进行排序,而不是排序
- 使用promise和mongoose对文档进行排序
- Selectize.js:如何对整数值的选项进行排序
- 使用php、ajax、javascript对页面上的flash文件进行随机排序
- 点击时对文本进行随机排序
- 使用 AJAX 回调更新挖空可观察数组会生成随机排序的结果
- 如何使用jquery随机元素排序
- jQuery显示为对元素进行随机排序
- 如何避免使用同位素与砌体布局随机排序的间隙
- 随机排序列表
- 从随机子项对列表项进行排序
- Javascript随机排序与种子
- 排序元素jQuery插件,随机排序
- 如何实现一个排序,但随机列表与javascript/jquery
- Javascript随机无法对项目进行排序,没有错误
- javascript中相同的随机排序
- 重新排序随机元素
- 数组的随机排序
- 在页面中随机排序列表项时缺少元素
- 非重复随机排序算法