编程语言
首页 > 编程语言> > javascript-在API响应中使用包含关系时,使用isPending,isSettled,isFulfilled的Ember 2行为异常

javascript-在API响应中使用包含关系时,使用isPending,isSettled,isFulfilled的Ember 2行为异常

作者:互联网

我需要彻底了解为什么财产会

isSettled
等待中
isFulfilled

如果我不包含API响应中的数据,则会有所不同.

我在这里问:https://discuss.emberjs.com/t/ember-2-show-a-single-loading-message-when-the-ids-where-included-in-the-original-response/12654,这使我想到了这种奇怪的行为:

如果我在我的API响应中包含数据(例如:model.posts),则这些属性会立即设置为true(并且.isPending为false),即使Chrome仍在加载实际数据(也是第一次!).

这是一个问题,因为我不知道posts []是否为空,也不知道该怎么做,因为类似的东西不起作用:

{{#each model.posts}}
  My posts.
{{else}}
  {{#if model.posts.isPending}}
    <div>Loading...</div>
  {{else}}
    <div>Nothing to show.</div>
  {{/if}}
{{/each}}

始终是“没什么可显示的”.直到加载Chrome.因为.isPending立即为假.

另外,如果我使用长度属性:

{{#if(eq model.posts.length 0)}}

因为起始posts []数组和空数组始终为length == 0.

如果我以不同的方式加载帖子,那么它可以异步运行,而不是侧面加载(但是有数百个HTTP请求,我不希望这样做).灰烬认出一个isPending …

为什么会有这种奇怪的行为?

UPDATE

我对/ category / 1的API响应:

{
  "data": {
    "id": "1",
    "type": "categories",
    "attributes": {
      "name": "Book"
    },
    "relationships": {
      "posts": {
        "data": [{
          "id": "11",
          "type": "posts"
        }, {
          "id": "14",
          "type": "posts"
        }, {
          "id": "16",
          "type": "posts"
        }]
      }
    }
  },
  "included": [{
    "id": "11",
    "type": "posts",
    "attributes": {
      "style": false,
      "comments": true
    }
  }, {
    "id": "14",
    "type": "posts",
    "attributes": {
      "style": true,
      "comments": false
    }
  }, {
    "id": "16",
    "type": "posts",
    "attributes": {
      "style": true,
      "comments": false
    }
  }]
}

因为我在Rails控制器中使用了include.

其他策略?

>嵌入式:ids?
> JSON API链接?

怎么做?

我唯一的小宝贝问题:

我不需要很多HTTP请求.在第一个模型(类别)之后,仅一个用于类别(模型),一个(非阻塞,带有加载消息).

解决方法:

好的,我想首先告诉您有关加载数据的不同方法.在您的示例中,您有两个模型.我知道一个叫做发布,现在就让另一个叫做我的模型.

现在,您之间有了一对多的关系.在我的模型中大概是这样的:

posts: hasMany('post'),

现在显然您想显示给定my模型的所有帖子.为此,您可能具有类似/ my-model-posts /:myModel_id的路由.一个非常有趣的问题是如何链接到该路线.这是因为对于链接,您已经需要my-model实例,现在的问题是如何加载该实例…

我将稍后讨论,现在让我们假设您的用户直接在给定的URL上访问您的应用程序,因为这是您始终必须处理的用例.

因为命名约定为model_id,所以您不必自己编写路线.但是请记住,默认实现将等效于此显式路由定义:

model(params) {
  return this.store.findRecord('my-model', params.myModel_id);
}

现在后端基本上有3种回应方式:

侧重一切

{
  data: {
    type: 'my-model',
    id: 'foo',
    attributes: {...},
    relationships: {
      posts: {
        data: [{
          type: 'post',
          id: '1'
        },{
          type: 'post',
          id: '2'
        }]
      }
    }
  },
  included: [{
    type: 'post',
    id: '1',
    attributes: {...}
  }, {
    type: 'post',
    id: '2',
    attributes: {...}
  }]
}

加载ID

{
  data: {
    type: 'my-model',
    id: 'foo',
    attributes: {...},
    relationships: {
      posts: {
        data: [{
          type: 'post',
          id: '1'
        },{
          type: 'post',
          id: '2'
        }]
      }
    }
  }
}

使用相关链接

{
  data: {
    type: 'my-model',
    id: 'foo',
    attributes: {...},
    relationships: {
      posts: {
        links: {
          related: '/api/model/foo/posts'
        }
      }
    }
  }
}

现在,您需要了解findRecord返回的promise将等待服务器的第一个响应,然后再解决.您的路由器将在输入路由之前等待此响应.了解这一点非常重要:在此承诺解决之前,您的路线将不会输入.要指示此阶段的加载状态,可以使用a loading substate..

因此,对于第一个示例,如果您分担所有工作,这就足够了.请记住,返回响应时,没有更多数据要加载.同样,在加载此响应之前,您将处于加载子状态.

最后一个例子也不是很难.一种简单的方法是显示两个加载微调器.您需要这样做,因为您发出了两个请求并且处于两种加载状态:

>用户点击路线
>您发出findRecord请求
>显示加载子状态,直到findRecord请求完成
>返回响应,并将呈现模板
>您访问model.posts,这将触发相关链接的加载.在加载数据时,model.posts.isPending将为true.您可以使用简单的{{#if model.posts.isPending}}正在加载… {{/ if}}来指示加载状态
>返回响应,并且model.posts.isPending现在为false.现在已加载所有数据.

但是,您可以根据需要随意修改以将其减少到一个加载状态.您可以将帖子加载到您的afterModel hook:

afterModel(model) {
  return model.get('posts');
}

这将强制在输入路线之前加载Promise帖子,使您始终处于loading substate.状态

另一件事是,如果您不关心my-model实例,则直接加载帖子:

model(params) {
  return this.store.findRecord('my-model', params.myModel_id)
    .then(m => m.get('posts'));
}

现在,模型将成为您的posts数组,并且您将一直处于loading子状态,直到发布posts为止.

最后但同样重要的是,我们来谈谈第二个示例:您仅加载ID.这可能是最棘手的问题.如果仅侧面加载id,则没有单个属性表示仍在加载某些内容.这是因为有许多HTTP请求,并且有很多承诺表明仍在加载某些内容.可能的唯一用例是当您实际上想尽快向用户显示数据时,因此我建议每篇文章使用加载优化程序:

{{#each model.posts as |post|}}
  {{#if post.isLoading}}
    loading...
  {{else}}
    ...the data...
  {{/if}}
{{else}}
  no posts
{{/each}}

请注意,如果您没有任何帖子,则必须先提出一个HTTP请求,这才是您所知道的!

如果您想要一个加载微调器,则可以在my-model上创建一个计算属性:

hasLoadingPosts: Ember.computed('posts.@each.isLoading', {
  get() {
    return this.get('posts').any(post => post.get('isLoading'));
  }
})

您也可以将其保留在loading子状态中,但这比较棘手:

afterModel(model) {
  return model.get('posts')
    .then(posts => Ember.RSVP.all(posts.toArray()));
}

您可以在模型挂钩中执行类似的操作:

model(params) {
  return this.store.findRecord('my-model', params.myModel_id)
    .then(m => m.get('posts'))
    .then(posts => Ember.RSVP.all(posts.toArray()));
}

还请注意,这最后两个承诺处理JS代码段在所有情况下均有效.如果数据已经加载,它们不会受到损害,但是要等待相关的链接以及侧面加载的ID.

现在,需要注意的一个非常重要的事情是通常不直接链接到这样的页面.可能您在某处有一个我的模型列表或其他内容,然后有一个链接以显示这些帖子.在这里,您将不会碰到模型钩!您也不需要此第一个请求:my-model的数据已在商店中!现在的问题是,首先加载它时返回了什么.您是否仅加载了ID或使用了相关链接来加载所有内容?结果与以上情况类似!

如果您修改了模型挂钩,则可能还应该将链接更改为从{{#link-到’my-model-posts’模型}}到{{#link-到’my-model-posts’模型.帖子}}.这很不错,因为如果您使用了相关链接,则路由将再次等待此承诺解决.

通常,我的建议是不要仅加载ID.这可能仅在您不将关系数据库用于后端的情况下才有用.

我建议使用相关链接,并在极少数情况下侧重加载所有内容.例如,如果您直接加载my-model,则将全部加载,而该列表仅返回相关链接.

现在只需要编程,因为只有相关的链接,通常情况下一切正常.如果有时需要较少的负载指示器,则可以.

另外,如果您仅显示此帖子数组,我将更改路线的语义并将其直接返回到模型挂钩中的数组中.当然,然后如上所述更改链接到.

但是,如果您想显示my-model的某些数据(例如标题),则可能希望尽快显示它们.在显示标题但还没有帖子时,这里需要isPending.

但是,如上所述,当您仅加载ID时,这两种解决方案都会中断.

标签:javascript,performance,rest,ember-js,ember-data
来源: https://codeday.me/bug/20191010/1884796.html