2015-07-21 81 views
0

刚开始使用Ember.js并且已经有一个愚蠢的问题!我想封装一些功能(将被几个不同的路由调用)。我不太确定把它放在哪里。正确放置此功能的地方?

的“程序”应做到以下几点:

  1. 调出到外部服务(目前WP REST API,但可能在未来数据库)来获取一些数据。
  2. 如果数据是JSON对象的数组,请提取第一个对象。
  3. 对该对象执行一些文本格式设置,具体请拨打htmlSafe()关于对象的HTML格式的内容属性。

这里是我试过到目前为止:

  • 执行所有的功能的帮手。看起来你不能从佣工那里退回承诺,所以这是行不通的。
  • 执行数据检索的util(从路径的model()导入并调用)和执行数据格式化的助手。这工作,但似乎笨拙?
  • 一个组件,它似乎没有一个良好的地方来进行AJAX调用。

这是一个绿地应用程序,所以我使用金丝雀的一些未来证明。出于这个原因,我不想使用三重卷曲。下面是我对中间(工作)选项代码:

应用程序/路由/ tos.js:

import Ember from 'ember'; 
import wpJson from '../utils/wp-json'; 

export default Ember.Route.extend({ 
    model() { 
    return wpJson('terms-of-use'); 
    } 
}); 

应用程序/ utils的/ WP-json.js:

/* global Ember */ 
export default function wpJson(slug) { 
    var url = `/wp-json/posts?type[]=page&filter[name]=${slug}`; 
    return Ember.$.getJSON(url).then(data => { 
    return data.shift(); 
    }); 
} 

app/templates/tos.hbs:

{{html-safe model.content}} 

应用程序/佣工/ HTML的safe.js:

import Ember from 'ember'; 

export function htmlSafe([html]) { 
    return html.htmlSafe(); 
} 

export default Ember.Helper.helper(htmlSafe); 

在某种完美的世界,app/routes/tos.js将是空的,app/templates/tos.hbs看起来会像这样:

{{wp-foo-bar slug='terms-of-use'}} 

谢谢提前提出任何建议或反馈意见。

回答

1

如何把所有的逻辑组件本身,就像这样:

//app/components/wp-foo-bar/component.js 
import Ember from 'ember'; 

export default Ember.Component.extend({ 

    remoteData: null, 

    loadingData: false,//maybe show spinner depending on this 

    fetchRemoteData: function(slug){  
     var url = '/wp-json/posts?type[]=page&filter[name]='+slug; 

     return new Ember.RSVP.Promise(function(resolve, reject){ 
     Ember.$.getJSON(url, function(data){ 
      resolve(data.shift()); 
     }); 
     }); 
    }, 

    didInsertElement: function(){ 
    var slug = this.get('slug'); 
    this.set('loadingData', true); 
    this.fetchRemoteData(slug).then(function(data){ 
     this.set('remoteData', data); 
     this.set('loadingData', false);    
    }.bind(this)); 
    } 
}); 

而且该组件的模板看起来像:

{{html-safe remoteData}} 
+0

感谢Deewendra。我有几个问题。没有得到JSON已经回复诺言?你为什么把它包装在一个新的承诺? – mwp

+0

虽然他们都是承诺,但他们是核心承诺概念的单独实施。 Ember使用RSVP lib来处理promise,并且根据我的个人经验,在编写集成testes时,当在Ember.RSVP承诺中包装jquery传递的对象/ promise时,这些事情只是“工作”。但只是不要说我的话,它只是个人的偏好 - 如果你没有在RSVP中包装,你很可能没有问题。推广 –

+0

好吧,明白了。再次感谢。在getJSON回调结束时,我似乎不需要'.bind(this)',或者至少在没有它的情况下工作。你能解释为什么它是必要的,以及如何用第二个回调来处理失败情况? – mwp

0

这是我的最终解决方案,基于客Deewandra的解决方案(我标记为“正确”)。主要区别在于使用ic-ajax,Freenode上的#emberjs中的人员因各种原因强烈推荐。我还删除了html-safe帮助程序,并在组件内移动了htmlSafe()函数调用。

我仍然困惑的唯一的事情是一些间歇性的警告,我已经看到关于不在didInsertElement()钩子内设置属性。我想我会留意它,因为Ember.js 2.0的成熟和我对框架的理解不断提高。

应用程序/组件/ WP-GET-page.js:

import Ember from 'ember'; 
import ENV from '../config/environment'; 
import ajax from 'ic-ajax'; 

export default Ember.Component.extend({ 
    slug: null, 
    isLoadingData: false, 
    remoteData: null, 

    didInsertElement() { 
    const slug = this.get('slug'); 
    if (Ember.isEmpty(slug)) 
     throw new Error('slug not specified in wp-get-page call'); 

    this.set('isLoadingData', true); 
    ajax(`${ENV.APP.WP_API_URL}/posts?type[]=page&filter[name]=${slug}`) 
     .then(data => { 
     if (Ember.isEmpty(data)) 
      throw new Error('no data from wp-json'); 

     if (Ember.isArray(data) && data.length === 1) 
      data = data.shift(); 

     this.set('remoteData', { 
      title: data.title, 
      content: data.content.htmlSafe() 
     }); 
     }) 
     .catch(() => { 
     this.set('remoteData', { 
      title: 'Sorry', 
      content: 'Unable to retrieve page contents! Please try again later.' 
     }); 
     }) 
     .finally(() => { 
     this.set('isLoadingData', false); 
     }); 
    } 
});