2015-07-21 95 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); 
     }); 
    } 
});