如何绑定Promise Knockout JS

时间:2016-05-17 09:54:52

标签: javascript knockout.js promise yelp

我有一个方法,通过yelp api返回带有一系列复杂对象的promise。 我需要通过data-bind =“foreach:objects”将它与标记绑定,但我不能。 我需要了解如何在标记中绑定数据,以及如何在可观察数组中使用promises。 有人可以帮忙吗?

//getDataForPlaces
var getDataForPlaces = function(addresses){
	return Promise.all(Array.prototype.map.call(addresses, function(address)    {
      return getLocationDesc(address);
   }));
	
};


//getLocationDesc

var getLocationDesc = function(address){
	return new Promise(function(resolve, reject) {
			var parameters = [];
            parameters.push(['sort', sort]);
            parameters.push(['limit', limit]);
            parameters.push(['radius_filter', radius_filter]);
            parameters.push(['actionlinks', actionlinks]);
            parameters.push(['location', address]);
            parameters.push(['callback', 'callback']);
            parameters.push(['oauth_consumer_key', auth.consumerKey]);
            parameters.push(['oauth_consumer_secret', auth.consumerSecret]);
            parameters.push(['oauth_token', auth.accessToken]);
            parameters.push(['oauth_signature_method', 'HMAC-SHA1']);

            var message = {
                'action' : 'http://api.yelp.com/v2/search',
                'method' : 'GET',
                'parameters' : parameters
            };

            OAuth.setTimestampAndNonce(message);
            OAuth.SignatureMethod.sign(message, accessor);

            var parameterMap = OAuth.getParameterMap(message.parameters);
            $.ajax({
                url : message.action,
                cache : true,
                method : message.method,
                data : parameterMap,
                dataType : 'jsonp',
                jsonp : 'callback',
                success : resolve,
                error : reject
            });
        });
	};


//View model

function MapViewModel(){
	var self = this;
	self.categories = ["Choose option", "Bars", "Gyms"];
	var addresses = ["address","address, address",
		"address","address",
		"address"]; 
	var yelp = new YelpDataProvider();

	self.places = ko.observableArray();

	yelp.getDataForPlaces(addresses).then(function(place){
		self.places(place);
	})
}

ko.applyBindings(new MapViewModel());
<ul data-bind="foreach: places ">
  <li data-bind="text: business[0].name"></li>
</ul>

复杂对象: enter image description here

1 个答案:

答案 0 :(得分:0)

这里有一个概念问题。

如果MapViewModel()是构造函数,则会使用new调用它。但是,构造函数的getLocationDesc()方面是异步的,其结果是,如所写的那样,new MapViewModel()将返回一个实际上仍在构建中的对象,并且无法获得表示完成的承诺异步过程。

构造函数和异步不混合。

解决方法是将异步内容放在公共.getLocationsAsync()方法中。这样的事情可能是:

function MapViewModel() {
    var self = this;
    self.categories = ["Choose option", "Bars", "Gyms"];
    self.places = ko.observableArray();
    var addresses = ["address", "address, address", "address", "address", "address"];
    var yelp = new YelpDataProvider();
    var locationsPromise = null;// a var in which to cache the promise created by this.getLocationsAsync()
    this.getLocationsAsync = function() {
        if(!locationsPromise) {
            locationsPromise = Promise.all(addresses.map(yelp.getLocationDesc)).then(function(placeDescriptions) {
                placeDescriptions.forEach(function(p) {
                    places.push(p);
                });
                return places;
            });
        }
        return locationsPromise;
    };
}

可能不是100%正确,但希望足以说明这个想法。

现在请致电如下:

var mapViewModel = new MapViewModel();
mapViewModel.getLocationsAsync().then(function(places) {
    // places is an observableArray
});

注意:要真正有用,您可能希望将addressescategories传递给MapViewModel(),否则每个实例都是相同的。或者也许MapViewModel()应该被改为单身?