【问题标题】:Ember (without ember-data) caching of data and defersEmber(没有 ember-data)缓存数据和延迟
【发布时间】:2013-04-04 10:27:09
【问题描述】:

我一直在尝试使用没有 ember-data 的 Emberjs。我正在尝试连接到现有的 JSON (但不是 REST) API。

我正在尝试加载一个缩略图网格,并通过单击它来呈现所选图像的高分辨率预览。

API 有单独的调用来获取文件集合以获取单个文件的详细信息。显然,我想避免为了获取预览高分辨率图像 URL 而拨打 100 次电话。因此我的 App.File.find 和 App.File.findAll 使用不同的 API 调用。

IMS.api.calljQuery.ajax 的简单包装器,它返回一个承诺。

问题:网格加载正常 (/#/files/) 但是,如果我单击单个图像,预览将使用缩略图而不是预览图像 (/#/files/11659315501)。但是,如果我刷新浏览器,我会得到一个高分辨率版本。

添加一些日志记录我看到在第一个版本中 App.File.find 从未被调用。刷新时会调用一次。

我尝试过的事情:

我添加了一个计算属性,它可以单独调用以获取高分辨率 url:

bigUrl: function(){
    var id = this.get('content.id');
    preview = App.File.find(id);
    return preview.url;         
}.property('id')

但是 jQuery 调用返回的延迟在视图呈现时尚未加载,因此 bigUrl 未定义。所以我尝试将其包装在一个承诺中,但 Ember 抱怨计算属性无法返回承诺。

我到处寻找如何鼓励 ember 致电 App.File.find,但无济于事。

有什么想法吗?

window.App = Ember.Application.create();

App.Router.map(function() {
  this.resource('files',function(){
    this.resource('file',{path:':file_id'});
  });
});

App.IndexRoute = Ember.Route.extend({
    redirect: function(){
        this.transitionTo('files');
    }
});

App.FilesRoute = Ember.Route.extend({
  model: function() {
    return App.File.findAll();
  }
});

App.FileRoute = Ember.Route.extend({
    model: function(args) {
        return App.File.find(args.file_id);
    }
});

App.File = Ember.Object.extend({});
App.File.reopenClass({
    find: function(id){
        return IMS.api.call("Files.GetAssetDetails",{"assetId":id}).then(
            function(response) {
                file = response.outParams;
                return App.File.create({'id':file.id,'filename':file.filename,"url":file.panoramicUrl});
            }
        );
    },  

    findAll: function() {
        return IMS.api.call("Files.GetAssetsForParent",{"containerId":11659314773}).then(
            function(response) {
                var files = [];
                response.outParams.forEach(function (file) {
                    files.push(App.File.create({'id':file.id,'filename':file.filename,"url":file.thumbUrl}));
                });
                return files;
            }
        );
    },
});

[更新]

视图如下所示:

应用:

<script type="text/x-handlebars" data-template-name="application">
  <div class="row">
    <div class="twelve columns">
      <h1>/pics/</h1>
      <hr>
      {{outlet}}
    </div>
  </div>
</script>

文件:

<script type="text/x-handlebars" data-template-name="files">
    <div class="row">

      <div class="six columns">
        {{outlet}}
      </div>

      <div class="six columns" id='chooser'>
        {{#each file in model}}
        <div style='float:left'>
          <div>
            {{#linkTo file file}}
              <img {{bindAttr src="file.url"}} style='width:100px;height:100px;'>
            {{/linkTo}}
          </div>
        </div>
        {{/each}}
      </div>
    </div>
</script>

文件

<script type="text/x-handlebars" data-template-name="file">
{{log id}}{{log url}}
  <div>
  <img {{bindAttr src="url"}} style='width:400px;height:400px;'>
  </div>
  <div>
    {{id}}
  </div>
</script>

【问题讨论】:

  • 您可以发布文件索引模板吗?我怀疑您可能将文件对象作为带有链接的上下文传递给那里。
  • 你的意思是,像:{{#linkTo file file}}?
  • 是的,我就是这个意思。但转念一想,可能已经为索引加载了一个具有正确 id 的文件,您只需要以某种方式刷新/更新它。
  • 我已经尝试过了 - 添加第二个 ajax 调用,该调用遍历所有文件并将 url 设置为更大的值。它不起作用,因为尽管数据正在更新,但视图从未刷新。
  • 试过在你的FileRoutesetupController 钩子里做这件事?

标签: model ember.js jquery-deferred


【解决方案1】:

要在每次路线更改时强制重新加载您的模型,您需要从setupController 进行调用。

每次路由更改时都会调用setupController。我选择将模型作为函数调用,而不是重复 App.File.find 调用。

App.FileRoute = Ember.Route.extend({
    setupController: function(controller,model){
        console.log("setupController",controller,model);
        controller.set('model',this.model({file_id:model.id}));
    },
    model: function(params) {
        return App.File.find(params.file_id);
    }
});

不幸的是,如果您要返回一个承诺,这将不起作用。要让它工作,你必须返回一个对象并承诺稍后填写。

find: function(id){
    file = App.File.create({});
    IMS.api.call("Files.GetAssetDetails",{"assetId":id,"fields":{"metadata":true}}).then(function(response) {
        file.setProperties({'id':response.outParams.id,'filename':response.outParams.filename,"url":response.outParams.panoramicUrl,"metadata":response.outParams.metadata});
        }
    );
    return file;
},  

这确实会偶尔出现一个错误:

TypeError: 'undefined' 不是一个对象(评估 'response.outParams.id')

这是由于setupController 没有从模型中获取有效的 id,然后将 undefined 交给它第一次调用它。

必须有更好的方法从路线中获取 id...有人吗?

[更新]

这是我停止错误的方法:

setupController: function(controller,model){
    if(model.isLoaded == false){
        controller.set('model',model);
    } else {
        controller.set('model',this.model({file_id:model.id}));
    }
},

我在查找函数中添加了一个“.isLoaded”标志:

find: function(id){
    file = App.File.create({isLoaded: false});
    IMS.api.call("Files.GetAssetDetails",{"assetId":id,"fields":{"metadata":true}}).then(function(response) {
        file.setProperties({'id':response.outParams.id,'filename':response.outParams.filename,"url":response.outParams.panoramicUrl,"metadata":response.outParams.metadata});
        file.set('isLoaded', true);
    });
    return file;
},  

【讨论】:

  • 您考虑过使用afterModel 挂钩吗?它适用于 promise。
猜你喜欢
  • 1970-01-01
  • 2014-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多