从路由访问服务的承诺

时间:2016-06-10 19:55:37

标签: ember.js ember-data

我正在努力争取服务承诺的路线数据。当我在应用程序init转换到Route时出现问题;也就是说,如果我加载应用程序,然后转换,一切都很好,因为承诺已经完成,但如果我在该路由上点击浏览器重新加载,则违规行将不会运行。该服务是:

// services/lime-core.js
import Ember from 'ember';

export default Ember.Service.extend({
  store: Ember.inject.service(),
  resources: null,

  init() {
    this.set('resources', []);

    this.get('store').findAll('resource').then(resources => {
      this.set('resources', resources);
    });
  }
});

假设我已将服务注入组件,此服务在模板中完美运行。我按如下方式在路径中访问此服务:(假设slug具有有意义的值)

// dashboard/route.js
export default Ember.Route.extend({
  limeCore: Ember.service.inject(),
  ...
  model(params) {
    ...
    this.set('resource', this.get('limeCore.resources').findBy('slug', slug));
    ...
  }
}

调用model()挂钩时,limeCore服务的init()方法仍在等待Promise履行。我试图变得聪明,但是将代码更改为:

this.get('limeCore.resources').then(resources => {
  this.set('resource', resources.findBy('slug', slug))
});

不起作用,因为this.get('limeCore.resources')不返回Promise。这个逻辑必须在路径中(即不能移动到模板),因为我依赖于slug值来确定加载一组不同的余烬数据的ID。

同样,一旦Promise完成,这段代码就可以正常工作 - 也就是说,在将来转换到这条路线时,而不是在初始应用程序加载时。

我确信有一个正确的方法可以做到这一点......服务需要返回一个Promise(同时仍然可以在模板中使用),或者我需要确保在{{{}之前完成Promise 1}}方法可以执行。

谢谢!

2 个答案:

答案 0 :(得分:0)

我会使用的方法

app/misc/lime_core.js

function getResources(store) {
     return store.findAll('resource')
}

export { getResources };

随机路线

import { getResources } from 'app/misc/lime_core';

export default Ember.Route.extend({
   model: function() {
     const store = this.get('store');
     const sourcePromise = getResources(store);
   }     
})

但如果您仍在寻找服务方法,我会像这样使用它

export default Ember.Service.extend({
  resources: null,
  store: Ember.inject.service(),


  getResources: function() {
     return this.get('store').findAll('source')
  }
});

路线

    limeCore: Ember.inject.service(),

    model: function() {
       const store = this.get('store');
       const sourcePromise = this.get('limeCore').getResources(); // sourcePromise.then(...

    } 

“我的路线的model()方法结果取决于资源的ID”

    model: function() {
       this.get('limeCore').getResources().then(sources => {
          return Ember.RSVP.hash({
               artifact: store.find('artifact', { source: source.get('firstObject.id)})
          })
       })
   }

或解决方案2

     model: function() {
           return Ember.RSVP.hash({
                   artifact: this.get('limeCore').getResources().then(sources => {
                       return store.find('artifact', {source: xx}) 
                  })
              })
           })
       }

您的getResources函数也可以按您的标准修改

function getResources(store) {
         return store.findAll('resource').then(r => r.findBy('id', 1))
}

答案 1 :(得分:0)

我认为我的问题措辞不当,所以我向读者道歉。发生这种情况是因为如果我正在提出问题,那通常是因为我无法表达问题。

上面提出的方法对我没有用,虽然它提供了一些有用的提示。重要的要求是(正如我在评论中提到的)我需要在模型查询中使用resource.id值。 kristjan的方法解决了这个问题,但我的问题没有充分说明model()方法有多复杂。

一个不成文的第二个要求是ajax请求只进行一次,因为数据很少改变,并且在应用程序加载的许多地方都需要。

最后,我能够使用kristjan方法的混合 - 创建一个limeCore.getResource()方法,该方法在Promise中加载数据,然后在我的路由的beforeModel()钩子中需要该promise。我意识到的关键是beforeModel(),就像model()一样,会等到Promise解析后再调用下一个钩子。在我的应用程序中,model()应该永远不会运行,直到这些核心对象被加载(model()依赖于它们),所以之前加载它们是有意义的。也许有一种更优雅的方法(我很容易听到),但此时我觉得这个问题已经解决了!

// services/lime-core.js
import Ember from 'ember';

export default Ember.Service.extend({
  store: Ember.inject.service(),
  resources: null,
  clients: null,

  init() {
    this.set('resources', []);
    this.set('clients', []);
  },

  // getCoreObjects() needs to be called at least once before the resources, clients and projects are available in the application. Ideally this method will be called in the route's beforeModel() hook. It cannot be called from the application route's beforeModel() hook because the code will not succeed if the user isn't authenticated.
  getCoreObjects() {
    if (this.get('resources').length === 0 || this.get('clients').length === 0) {
      return Ember.RSVP.hash({
        resources: this.get('store').findAll('resource').then(resources => {
          this.set('resources', resources);
        }),
        clients: this.get('store').findAll('client', {include: 'projects'}).then(clients => {
          this.set('clients', clients);
        })
      });
    } else {
      return Ember.RSVP.hash({});
    }
  }
});

在我的路线中:

// routes/dashboard.js
import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

export default Ember.Route.extend(AuthenticatedRouteMixin, {
  limeCore: Ember.inject.service(),
  session: Ember.inject.service(),
  ...
  beforeModel(transition) {
    this._super(...arguments);
    if (this.get('session.isAuthenticated')) {
      return this.get('limeCore').getCoreObjects();
    }
  },

  model(params) {
    ...
    this.set('resource', this.store.peekAll('resource').findBy('slug', slug));
    ...
    return this.store.query('artifact', {'resource-id': this.get('resource.id')});
  }
}
相关问题