如何让Ember路线模型的一部分成为承诺?

时间:2017-12-06 17:00:31

标签: javascript ember.js promise

我有一个像这样的简单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

以下也有效,现在使用整个模型的承诺:

// 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(),但如果任何承诺拒绝,那将拒绝。是否有可能对路线模型的不同部分有独立承诺,或者只有全有或否?

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

2 个答案:

答案 0 :(得分: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,这将返回undefined,直到promise返回。

答案 1 :(得分:0)

在最后一种情况下,

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);
    });

  }