如何仅使 Ember 路由模型的一部分成为承诺?

How to make only part of Ember route model a 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>)。

在最后一个案例中,

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

  }

您可以使用来自 ember-data:

PromiseObject or PromiseArray
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,它将 return 未定义,直到承诺 returns.