使用返回的promise数据

时间:2014-10-21 20:43:49

标签: javascript ember.js promise

我有类似的东西:

App.IndexController = Ember.ObjectController.extend({
   results : function(){

      return new Ember.RSVP.Promise(function(resolve, reject){

        Ember.$.getJSON('/search').then(function(res){
          console.log('response data is: ', res);
          resolve(res)
        })

      })

   }.property(),
  ...
})

// data
$.mockjax({
  url: '/search',
  responseText : {
    type: 'different people',
    res: [
      {name: 'charlie', age: '55'},
      {name: 'bobby', age: '19'},
      {name: 'raymond', age: '39'}
    ]
  }
})

my jsbin

如何实际使用返回的数据?目前,results会返回一个承诺(this.get('results')),因此我无法在我的hbs模板中使用它。我是否需要将其转换为对象然后返回该对象?

2 个答案:

答案 0 :(得分:1)

回答问题

内部的恩伯使用PromiseProxyMixin来做我们所知道和喜爱的承诺的神奇渲染。这是您使用PromiseProxy更新的JSBin:

http://emberjs.jsbin.com/danazu/edit?html,js,output

您的results财产变为:

results: Ember.computed.promise(function(resolve, reject) {
  Ember.$.getJSON('/search').then(function(res) {
    console.log('response data is: ', res);
    return resolve(res);
  });
})

但是我不推荐这个。请查看this discourse thread以获取有关您可能不想这样做的原因的信息。简而言之,处理所有不同的承诺状态将是笨拙的。

寻找更好的方式

路由器是处理AJAX请求的承诺的理想之地。必须有一些原因,您不仅要在modelafterModel挂钩中将此数据加载到路由器中。您是否可以创建另一个嵌套资源来表示这些搜索结果,然后只创建link-to该资源?

在你的路由器中:

Router.map(function() {
  this.resource('search', { path: '/search/:term' });
});

App.PeopleRoute = Ember.Route.extend({
  model: function(params) {
    return Ember.$.getJSON('/search?term=' + params.term);
  }
});

如果这至少不能奏效,你可以:

  1. 如果您想要搜索结果
  2. ,请发送action
  3. 处理控制器中的AJAX请求
  4. 解析后,在控制器上设置results

答案 1 :(得分:0)

我使用ic ajax来轻松使用promises。我目前没有使用Ember数据,所以我在ic ajax上写了一个很好的休息客户端,以便轻松获取/发布/放入网址:

rsvpAjax: function(url,method, data){
      var headers = {};

      // build request
      var opts = {};
      var defaultOpts = {
        type: method,
        headers: headers,
        data: JSON.stringify(data),
        dataType: 'json',
        xhrFields: {
          withCredentials: true
        }
      };
      return ajax.request(url, $.extend({}, defaultOpts, opts));
}

然后我得到方法:

getAsync: function(url){
      return this.rsvpAjax(url, "GET");
}

然后在facade / helper类的其他地方使用它:

import objFactory from 'appname/models/obj';
...
...
foo: function(){
        //get your rest client somehow
        var apiFacade = this.getRestClient();
        return restClient.getAsync('url_string').then(function(response){
            //targets some part of the response - here its an array of 
            var data = response.data;
            return data.map(function(obj){
                return objFactory.create(obj);
            });
        });
}

foo返回一个Ember对象数组。 objFactory我导入的只是一个Ember.Object类。传递给创建的obj通常与所述Ember.Object中的属性一对一匹配。使用初始化程序,我将此对象注入每个路径:

import someFacade from "app/facades/facade";

export default {
    name: 'someFacade',

        initialize: function(container, app) {
        //a singleton by default
        container.register('facades:someFacade',someFacade);
        app.inject('route', 'someFacade', 'facades:someFacade');
    }
};

由于DI,我的任何路线都可以使用此外观而无需导入。

//Ember blocks
model: function(){
    return this.someFacade.foo();
}

或:

setupController(controller, model){
    //set controller prop on return of resolved val
    this.someFacade.foo().then(function(foosReslovedVal){
        controller.set('someProp', foosResolvedVal);
    });   
}