简体   繁体   English

如何从Promise Knockout JS绑定对象数组

[英]How to bind array of objects from Promise Knockout JS

I have a method which returns promise with an array of complex objects via yelp api. 我有一个通过yelp api返回带有复杂对象数组的promise的方法。 I need to bind it with markup by data-bind="foreach: objects", but I can't. 我需要通过data-bind =“ foreach:objects”将其与标记绑定,但是我不能。 I need to understand how to bind data in markup, and how to work with promises in observable arrays. 我需要了解如何在标记中绑定数据,以及如何在可观察的数组中使用Promise。 Can anyone help? 有人可以帮忙吗?

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

complex object: 复杂对象: 在此处输入图片说明

There's a bit of a conceptual issue going on here. 这里有一些概念上的问题。

If MapViewModel() is a constructor, it will be called with new . 如果MapViewModel()是构造函数,则将使用new调用它。 However, the getLocationDesc() aspect of the constructor is asynchronous, with the consequence that, as written, new MapViewModel() will return an object which is effectively still under construction, and with no access to a promise to signify completion of the async process. 但是,构造函数的getLocationDesc()方面是异步的,其结果是,按照书面规定, new MapViewModel()将返回有效地仍在构造中的对象,并且无法访问表示完成异步过程的承诺。 。

Constructors and asynchronism don't mix. 构造函数和异步性不能混在一起。

A workaround is to put the async stuff inside a public .getLocationsAsync() method. 一种解决方法是将异步内容放入公共.getLocationsAsync()方法中。 Something like this maybe : 可能是这样的:

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;
    };
}

Probably not 100% correct but hopefully good enough to illustrate the idea. 可能不是100%正确,但希望足以说明这一想法。

Now call as follows : 现在调用如下:

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

Note: To be truly useful, you probably want to pass addresses and categories to MapViewModel() , otherwise every instance will be identical. 注意:要真正有用,您可能希望将addressescategories传递给MapViewModel() ,否则每个实例都是相同的。 Or maybe MapViewModel() should be rephrased as a singleton? 还是应该将MapViewModel()改写为单例?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM