2016-04-29 2 views
3

Я пытаюсь сделать вызов внешнего API и использовать результаты как вычисленное свойство в моей модели Ember Data. Результат получается нормально, но вычисляемое свойство возвращается до разрешения Promise, что приводит к неопределенному. Это прецедент для наблюдателя?Результат обещания в Ember Вычисленное значение данных

export default DS.Model.extend({ 
    lat: DS.attr(), 
    lng: DS.attr(), 
    address: Ember.computed('lat', 'lng', function() { 
    var url = `http://foo.com/json?param=${this.get('lat')},${this.get('lng')}`; 
    var addr; 

    var request = new Ember.RSVP.Promise(function(resolve, reject) {    
     Ember.$.ajax(url, {               
      success: function(response) {            
      resolve(response);              
      },                  
      error: function(reason) {             
      reject(reason);               
      }                   
     });                   
    });                   

    request.then(function(response) {      
     addr = response.results[0].formatted_address;        
    }, function(error) {               
     console.log(error); 
    }) 

    return addr; 
    }) 
}); 
+0

Извините, я удалил свои ответы, поскольку они не работают .. :((см. Это для получения дополнительной информации) http://discuss.emberjs.com/t/promises-and-computed-properties/3333] –

+0

Лучшей техникой было бы использование компонента для отображения адреса с учетом lat и lng в качестве входных данных. Он может запускать запрос в его методе 'init' и устанавливать свойство отображения в функции' success'. –

+0

Спасибо за ваш помогите Стиву! Приведенная выше ссылка дала ответ, который работает. Мне это нравится лучше, чем компонентное решение, так как оно поддерживает логику, содержащуюся внутри модели. – codyjroberts

ответ

3

Использование DS.PromiseObject. Я использую следующую технику все время:

import DS from 'ember-data'; 

export default DS.Model.extend({ 

    ... 

    address: Ember.computed('lat', 'lng', function() { 
    var request = new Ember.RSVP.Promise(function(resolve, reject) {    
     ... 
    });                   

    return DS.PromiseObject.create({ promise: request }); 
    }), 

}); 

Используйте разрешенное значение в шаблонах, как {{address.content}}, который будет автоматически обновлять при проксированной Promise решает.

Если вы хотите сделать больше, здесь я бы рекомендовал проверить, что другие люди в сообществе делают: https://emberobserver.com/?query=promise

Это не так уж трудно построить простой компонент, который принимает DS.PromiseObject и показать загрузки спиннера время обещание все еще находится на рассмотрении, а затем показывает фактическое значение (или доходность к блоку), как только Promise разрешается.

У меня есть приложение Ember.Service в приложении, над которым я работаю, который состоит почти полностью из вычисленных свойств, которые возвращают обещания, завернутые в объекты DS.PromiseObjects. Он работает удивительно легко.

+0

Awesome. Не знал о 'PromiseObject'. Я попробую. – codyjroberts

+0

+1, чтобы избежать ручной настройки значения вычисленного значения и для использования определенного класса Ember, созданного для этого варианта использования – jessica

0

Создание компонента (адрес-display.js):

import Ember from 'ember'; 

export default Ember.Component.extend({ 
    init() { 
    var url = `http://foo.com/json?param=${this.get('lat')},${this.get('lng')}`; 
    Ember.$.ajax(url, { 
     success: function(response) { 
     this.set('value', response.results[0].formatted_address); 
     }, 
     error: function(reason) { 
     console.log(reason); 
     } 
    }); 
    } 
}); 

шаблона (компоненты/адрес-display.hbs):

{{value}} 

Затем использовать компонент в шаблоне :

{{address-display lat=model.lat lng=model.lng}} 
-1

Нижеследующие работы b y, разрешая внутри свойства и устанавливая результат.

Разъяснения здесь: http://discuss.emberjs.com/t/promises-and-computed-properties/3333/10

export default DS.Model.extend({ 
    lat: DS.attr(), 
    lng: DS.attr(), 
    address: Ember.computed('lat', 'lng', function() { 
    var url = `http://foo.com/json?param=${this.get('lat')},${this.get('lng')}`; 
    var self = this; 

    var request = new Ember.RSVP.Promise(function(resolve, reject) {    
     Ember.$.ajax(url, {               
      success: function(response) {            
      resolve(response);              
      },                  
      error: function(reason) {             
      reject(reason);               
      }                   
     });                   
    }).then(function(response) { 
     self.set('address', response.results[0].formatted_address); 
    }) 
    }) 
}); 
1

Я использовал self.set('computed_property', value); технику в большом приложении Ember в течение трех месяцев, и я могу вам сказать, что есть очень большая проблема: вычисленное свойство будет только работать один раз.

Когда вы вычислено значение вычисленного значения, функция, сгенерировавшая результат, теряется, поэтому, когда ваши связанные свойства модели изменяются, вычисленное свойство не будет обновляться.

Использование обещаний внутри вычисляемых свойств в Эмбер хлопот, лучший метод, который я нашел это:

prop: Ember.computed('related', { 
    // `get` receives `key` as a parameter but I never use it. 
    get() { 
     var self = this; 
     // We don't want to return old values. 
     this.set('prop', undefined); 
      promise.then(function (value) { 
       // This will raise the `set` method. 
       self.set('prop', value); 
      }); 
     // We're returning `prop_data`, not just `prop`. 
     return this.get('prop_data'); 
    }, 
    set(key, value) { 
     this.set('prop_data', value); 
     return value; 
    } 
}), 

Плюсы:

  • Он работает на шаблонах, так что вы можете сделать {{object.prop}} в шаблоне и он будет исправляться должным образом.
  • Он обновляется при изменении связанных свойств.

Минусы:

  • Когда вы делаете в Javascript object.get('prop'); и обещание решения, он будет возвращать вам inmediately undefined, однако, если вы наблюдаете вычисленное свойство, наблюдатель будет вести огонь снова, когда обещает решение, и окончательное значение установлено.

Возможно, вам интересно, почему я не вернул обещание в get; если вы это сделаете и используете в шаблоне, оно отобразит представление строки объекта ([object Object] или что-то в этом роде).

Я хочу работать в правильной реализации вычисляемого свойства, которая хорошо работает в шаблонах, возвращает обещание в Javascript и автоматически обновляется, возможно, используя что-то вроде DS.PromiseObject или Ember.PromiseProxyMixin, но, к сожалению, я не нашел для этого времени.

Если большой жулик не является проблемой для вашего Прецедент использовать метод «получить/установить», если не пытаться реализовать лучший метод, но серьезно не просто использоватьself.set('prop', value);, это даст вашему много проблем в долгосрочной перспективе, это не стоит.

PS.: Реальное, окончательное решение для этой проблемы, однако, заключается в следующем: никогда не используйте обещания в вычисленных свойствах, если вы можете избежать этого.

PS.: Кстати, эта техника не моя, а мой бывший сотрудник @ перезагрузка перезагрузки.

+0

Спасибо за ввод! У меня еще не было проблемы с self.set, но я дам ему попытку и отправлю отчет. Я немедленно возвращаю значение, чтобы не делать имеют неопределенный вопрос. Эта работа отлично подходит для информирования пользователя о прогрессе. – codyjroberts

+0

Можно сообщить, что это хорошо работает, я исключил 'prop_data'. «Self.set» - ключевой момент здесь – oden

Смежные вопросы