2016-10-26 31 views
0

在我的應用程序中,我使用knockoutJS作爲框架,並且想要查詢API以獲取數據。預期行爲是在KO的可觀察數據中設置數據,然後UI將自動更新。該HTML雲如下:Knockoutjs:如何將異步API查詢結果設置爲observables

<div class="container"> 
     <div class="options-box"> 
     <h1>Restaurant Finder</h1> 
     <ul class="category-list" data-bind="foreach: categoryList"> 
      <li class="category-item" data-bind="text:$data, click: $parent.queryRestaurant"></li> 
     </ul> 
     <ul class="location-list" data-bind="foreach: locationList"> 
     <li class="location-item" data-bind="text: title"></li> 
     </ul> 
    </div> 
    </div> 

和JS代碼放在如下:

$(function(){ 
    console.log("debug inside the initmap") 
    //The predefined restaurant categrory 
    var restaurantCate = ["Sushi","Chinese Food","Coffee"]; 
    // the Location function for creating new location Knockout object 
    var Location = function(loc){ 
     return ko.observable(loc); 
    }; 
    //the locatoinViewModel is the view model part for this application 
    var locationViewModel =function() { 
     var self = this; 
     self.locationList = ko.observableArray([]); 

     self.categoryList = ko.observableArray(restaurantCate); 
     self.queryRestaurant = function(){ 
      console.log("hi"); 
      var foursquare_url = "https://api.foursquare.com/v2/venues/search"; 
      var Client_ID="xxx"; 
      var Client_Secret="xxx"; 
      foursquare_url += "?client_id=" + Client_ID + "&client_secret=" + Client_Secret + "&v=20130815" + "&ll=40.7413549,-73.9980244" + "&query=" + this; 
      console.log(foursquare_url); 
      queryFoursquare(foursquare_url); 
     }; 
    }; 
    ko.applyBindings(new locationViewModel()); 
    //the queryFoursquare function 
    function queryFoursquare(queryurl){ 
     $.getJSON(queryurl,function(response){ 
      console.log(response["meta"]["code"]); 
      var result = []; 
      response["response"]["venues"].forEach(function(eachvenue){ 
       result.push({ 
        title: eachvenue["name"], 
        location: {lat: eachvenue["location"]["lat"], lng:eachvenue["location"]["lng"]} 
       }); 
      }); 
      locationViewModel.locationList(result); 
     }).done(function(){ 
      console.log("done") 
     }).fail(function(){ 
      alert("error happens during query data from Foursquare") 
     }); 

    };  
    }); 

現在的狀態是:KO的視圖模型可以很好地工作和API函數可以得到的數據也是如此。
問題是如何將result數組設置爲KO的observableArray locationList。如何處理這種異步查詢案例?

編輯: 我忘了添加錯誤消息:locationViewModel.locationList is not a function

編輯II

 var locationViewModel =function() { 
     var self = this; 
     self.locationList = ko.observableArray([]); 

     self.categoryList = ko.observableArray(restaurantCate); 
     self.queryRestaurant = function(){ 
      console.log("hi"); 
      var foursquare_url = "https://api.foursquare.com/v2/venues/search"; 
      var Client_ID="T3A2F5ZKOVEDWXZXLHFFNPU3DYTYIUZGPJELBWLJZVQFTALA"; 
      var Client_Secret="IM2R2QRHZR0CIOGCLYKGTOSBEPERM1JVA0X022CY3B4ZX41P"; 
      foursquare_url += "?client_id=" + Client_ID + "&client_secret=" + Client_Secret + "&v=20130815" + "&ll=40.7413549,-73.9980244" + "&query=" + this; 
      console.log(foursquare_url); 
      //queryFoursquare(foursquare_url); 
      //Directly call the getJSON function inside viewmodel 
      $.getJSON(foursquare_url,function(response){ 
       //console.log(response["meta"]["code"]); 
       var result = []; 
       response["response"]["venues"].forEach(function(eachvenue){ 
        result.push({ 
         title: eachvenue["name"], 
         location: {lat: eachvenue["location"]["lat"], lng:eachvenue["location"]["lng"]} 
        }); 
       }); 
       self.locationList(result) 
      }); 
     }; 
    }; 

所以把AJAX調用回viemmodel後。然後按照self.locationList的行爲按預期行事。 如果我想將API調用分離成一個函數,如何訪問KO的observables?

謝謝因此,基於更新後

+0

你正在公開你的客戶端ID和祕密世界... – haim770

回答

1

,把它歸結爲分離視圖模型的queryFoursquare功能。而不是試圖訪問locationList裏面的功能,你可以從函數返回result和返回值賦給locationList像下面 -

//return the result array - 

return $.getJSON(foursquare_url, function(response) { 
    //console.log(response["meta"]["code"]); 
    var result = []; 
    response["response"]["venues"].forEach(function(eachvenue) { 
    result.push({ 
     title: eachvenue["name"], 
     location: { 
     lat: eachvenue["location"]["lat"], 
     lng: eachvenue["location"]["lng"] 
     } 
    }); 
    }); 
    return result; 
}); 

// Assign the return value to the locationList observable Array. 
queryRestaurant().done(function(result) { 
    //Do stuff with the response. 
    self.locationList(dataPreparedFromResult); 
    console.log(self.locationList()); 
}); 

這將使你的代碼更可重用。

編輯

所以,你需要從你的queryRestaurant函數返回一個承諾,在.done處理器,你需要推觀察到陣列中的數據。因爲,分配是在承諾返回前完成的,所以您得到undefined作爲輸出。

希望這最終有助於...

+0

Thx。但我認爲關鍵是如何根據錯誤消息「locationViewModel.locationList不是函數」訪問viewmodel外部的'locationList'。請在原文中查看我的編輯。 –

+0

現在這個錯誤使我們處於不同的情況。我認爲現在它取決於很多事情,queryFoursquare函數保留在哪裏,如果是特殊的視圖模型,那麼問題是在不同的視圖模型/模塊之間進行通信。你用什麼來解決依賴關係,等等。 – gkb

+0

THx。爲了簡化問題,我只有一個視圖模型。這裏發佈的代碼都是東西。尊敬的 –

相關問題