【问题标题】:How to make only part of Ember route model a promise?如何仅使 Ember 路由模型的一部分成为承诺?
【发布时间】:2017-12-06 17:00:30
【问题描述】:

我有一个简单的template.hbs 像这样:

// template.hbs

<p>{{model.x}}</p>
<p>{{model.y}}</p>

以下 route.js 按预期工作:

// route.js

import Route from '@ember/routing/route';

export default Route.extend({

    model() {

        return {
            x: 'foo',
            y: 'bar'
        };

    }
});

// output, immediately:
// foo
// bar

以下方法也可以使用,现在对整个模型使用 Promise:

// route.js

import Route from '@ember/routing/route';
import RSVP from 'rsvp';

export default Route.extend({

    model() {

        return new RSVP.Promise((resolve) => {
            setTimeout(() => {
                resolve({
                    x: 'foo',
                    y: 'bar'
                });
            }, 1000);
        });

    }
});

// output, after 1s:
// foo
// bar

以下内容,我只想对model.x 做出承诺 - 不起作用。

// route.js

import Route from '@ember/routing/route';
import RSVP from 'rsvp';

export default Route.extend({

    model() {

        return {
            x: new RSVP.Promise((resolve) => {
                setTimeout(() => {
                    resolve('foo');
                }, 1000);
            }),
            y: 'bar'
        };

    }
});

// output, IMMEDIATELY:
// [object Object]
// bar

它立即渲染输出,但在进入setTimeout 中的回调后,它不会更改model.x 的渲染值。

我知道RSVP.hash(),但如果任何承诺被拒绝,那将被拒绝。是否可以对路由模型的不同部分有独立的 Promise 或只有全有或全无?

奇怪的是,如果有问题的承诺是由 ember-data 返回的,例如x: this.get('store').findRecord('user'),它可以正常工作(例如将template.hbs 更改为&lt;p&gt;{{model.x.name}}&lt;/p&gt;)。

【问题讨论】:

    标签: javascript ember.js promise


    【解决方案1】:

    您可以使用来自 ember-data 的 PromiseObjectPromiseArray

    export default Ember.Route.extend({
      model() {
            return {
                x: DS.PromiseObject.create({
                  promise: new RSVP.Promise((resolve) => {
                      setTimeout(() => {
                          resolve({name: 'foo'});
                      }, 5000);
                  })
                }),
                y: 'bar'
            };
        }
    });
    

    为此,您的承诺结果必须是一个对象(即{name: 'foo'} 而不仅仅是foo)。然后你可以在你的模板中使用x.name,它会在promise返回之前返回undefined。

    【讨论】:

    • 靶心!谢谢你,@Enno!
    【解决方案2】:

    在最后一种情况下,

    model.x 是 Promise 对象,如果你在 hbs 中做{{log model.x}},你可以在控制台看到它。您可以尝试使用{{model.x._result}} 访问该值。但这不是正确的做法。

    在你的情况下,你可以尝试实现路由的 setupController 钩子,

    setupController(controller,model)
      {
        this._super(...arguments);
        let xPromise = new RSVP.Promise((resolve) => {
                    setTimeout(() => {
                        resolve('foo');
                    }, 1000);
                });
        xPromise.then((result) =>{
          this.set('model.x',result);
        });
    
      }
    

    【讨论】:

    • 感谢您的回答!但是,我正在寻找一种直接从模型钩子中利用 Promise 的方法。这解决了问题,但它看起来也像黑客攻击。
    猜你喜欢
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    • 1970-01-01
    • 2012-08-01
    相关资源
    最近更新 更多