2016-02-12 92 views
1

下面是一些重複的問題更新淘汰賽observableArray產生隨機排序結果

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結果,所以我需要索引的結果是一樣的地方各自的條目索引[]

+1

我想你可能有這個問題的僞裝重複:[元素順序在「for(... in ...)」循環](http://stackoverflow.com/a/280861/419956)?如果訂單很重要,你應該對自己進行排序。 (注意,如果你需要一個* stable *排序,你也應該有一個明確的tiebreaker,因爲在Javascript中的數組排序並不保證是一個穩定的排序 - AFAIK。) – Jeroen

+0

所以我想這意味着沒有簡單的解決方案。大。 – Brushline

+0

爲什麼不呢?如果你從'for..in'變成一個正常的'for'循環,事情應該解決,對嗎? – Jeroen

回答

1

你有兩個問題與秩序:

  • for.in不保證訂單;
  • 你在回調中異步填寫observableArray,但不能保證它們會到達以便將它們解僱!

後者可能是最突出的問題。您當前push結果到您的可觀察數組中,但是您按照瀏覽器返回結果的順序執行此操作。

這是你的問題稍微最小的攝製,用不同的回調時機exagerated:

// 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>

正如你所看到的,每次你的時候運行這個你有機會結果是失序的。

選項1splice new items into the array處於您想要的位置(而不是使用push)。這是國際海事組織有點複雜的做法,我將把代碼留給讀者。

選項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> 

...如果需要。