【问题标题】:How can a graphql mutation automatically refresh a query being watched by Apollo Client?graphql 突变如何自动刷新 Apollo 客户端正在监视的查询?
【发布时间】:2017-11-28 03:11:44
【问题描述】:

最近开始使用 graphQL 和 Apollo - apollo-client。

我在 graphQL 之上构建了一个 Web 服务,它运行良好。我面临的唯一问题是在项目的客户端。例如(请参阅下面的代码),在运行 createVideo() 之后,我的组件的 data 属性是一个观察查询不会自动刷新并且在回调上手动调用 apollo.query 似乎没有生效,因为查询返回缓存的结果,而不是来自服务器的结果。

我错过了什么吗?


app.component.ts
  import {Component, OnInit} from '@angular/core';
  import {Apollo, ApolloQueryObservable} from 'apollo-angular';
  import 'rxjs/Rx';
  import gql from 'graphql-tag';

  // http://dev.apollodata.com/angular2/mutations.html
  const NewVideoQuery = gql`
    mutation AddVideoQuery($title: String!,$duration: Int!, $watched: Boolean!){
      createVideo(video: { title: $title, duration: $duration, watched: $watched } ){
        id,
        title
      }
    }
  `;
  const VideoQuery = gql`
      {
          videos {
              id,
              title
          }
      }
  `;
  @Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
  })
  export class AppComponent implements OnInit {
    data: ApolloQueryObservable<any>;
    video: any = {};

    constructor(private apollo: Apollo) {
    }

    ngOnInit() {
      this.data = this.apollo.watchQuery({query: VideoQuery});
    }

    createVideo() {
      /**
       * This will send a mutate query to the server.
       */
      // @todo After running the mutate, the watch query doesn't refresh
      this.apollo.mutate({
        mutation: NewVideoQuery,
        variables: {
          'title': this.video.title || 'Some Video' + Math.floor(Math.random() * 10),
          'duration': 123213,
          'watched': true
        }
      }).subscribe((afterMutation) => {
        console.log(afterMutation);
        // This fires but query doesn't hit the server since it's coming from cache.

        // @todo Not even by re-running it here
        this.apollo.query({query: VideoQuery})
          .subscribe((data) => {
            console.log(data);
          });
      }, (err) => alert(err));
    }
  }

//app.component.html

  <div *ngFor="let x of data | async | select: 'videos'">
   <div><b>{{x.id}}</b>{{x.title}}</div>
  </div>

  <label>
    Title
    <input type="text" [(ngModel)]="video.title">
  </label>

  <button (click)="createVideo()">{{title}}</button>

【问题讨论】:

    标签: angular graphql apollo


    【解决方案1】:

    我想通了。 Apollo-client 默认缓存我们的查询,重新运行相同的查询当然会从缓存而不是服务器返回结果。

    当然,因为我做了一个突变来创建一条新记录,我希望服务器会自动刷新数据集,但事实并非如此。

    为了解决这个问题,我想出了从 createVideo 突变的成功回调中重新运行查询的想法,但这次我添加了一个名为 fetchPolicy 的特殊选项,它支持以下值:

    'cache-first' | 'cache-and-network' | 'network-only' | 'cache-only' | 'standby'
    

    最后我的 fetch 查询如下所示:

    this.apollo.query({query: VideoQuery, fetchPolicy: 'network-only'})
    .subscribe(()=>{ console.log('refresh done, our watchQuery will update') })
    

    额外提示:

    关于 Apollo 的另一个有趣的功能是您可以像这样设置池化间隔,以便您的数据始终与服务器同步

    this.data = this.apollo.watchQuery({query: VideoQuery, pollInterval: 10000});
    

    【讨论】:

    【解决方案2】:

    我建议您使用 fetchPolicy: 'cache-and-network',因为它会获取已存储的数据,但还会更新缓存,使您的查询更快,但仍会更新您的缓存。您可以在此处阅读有关了解 Apollo Fetch 策略的更多信息 --> https://medium.com/@galen.corey/understanding-apollo-fetch-policies-705b5ad71980

    【讨论】:

      猜你喜欢
      • 2019-02-02
      • 2018-05-21
      • 2020-06-07
      • 2019-11-02
      • 2020-06-14
      • 2020-08-25
      • 2020-09-29
      • 2016-08-31
      相关资源
      最近更新 更多