2019.02.14
Apollo Clientを勉強していて、おそらくデータの読み出しと監視を行なっているreadQuery
メソッドとwatchQuery
メソッドが出てきたので、公式ドキュメントを読んで概要を把握する。
Tries to read some data from the store in the shape of the provided GraphQL query without making a network request. This method will start at the root query. To start at a specific id returned by dataIdFromObject use readFragment.
(意訳)ネットワーク通信を行わずに、GraphQLのクエリの形式でストアからデータ取得する。このメソッドはroot queryからスタートする(訳注:現時点では意味不明...)。dataIdFromObjectで返されるIDから始めるには、readFragmentを利用する。
通信せずにキャッシュからデータを読み出すメソッドとのこと。リストのような構造をしているデータを先頭から読み込むイメージ?readFragment
を使うことで位置を指定してデータを読み込めるということ?
後ほど実際に動かしながら検証したい。
watchQuery(options) - Apollo Client
This watches the cache store of the query according to the options specified and returns an ObservableQuery. We can subscribe to this ObservableQuery and receive updated results through a GraphQL observer when the cache store changes.
(意訳)オプションを指定してキャッシュストアを監視しObservableQueryを返す。ObservableQueryを購読することで、キャッシュストアが変更されたときに更新情報を受け取ることができる。
キャッシュストアの変更を監視することができるということは、Optimistic Responseの内容もここで受け取ることができるかもしれない。
Note that this method is not an implementation of GraphQL subscriptions. Rather, it uses Apollo's store in order to reactively deliver updates to your query results.
(意訳)このメソッドはGraphQLのSubscriptionの実装ではないことに注意。むしろ、クエリの結果をリアクティブに伝播させるためにストアにアクセスする。
GraphQLサーバーからプッシュされる情報を購読するものではないとのこと。
For example, suppose you call watchQuery on a GraphQL query that fetches a person's first and last name and this person has a particular object identifer, provided by dataIdFromObject. Later, a different query fetches that same person's first and last name and the first name has now changed. Then, any observers associated with the results of the first query will be updated with a new result object.
(意訳)一意の識別子をもつユーザーの氏名を取得するようなGraphQLのqueryをwatchQueryを呼ぶケースを想定する。後に、他のクエリで同じユーザーの氏名を取得したとして、その時点で取得するユーザーの氏名は変更されているとする。そのとき、最初のクエリ結果を購読しているObserverには新しいオブジェクトが流れてくる。
watchQuery
しておけば、変更されたときにUIの各部分がリアクティブに書き変わるということらしい。
Note that if the cache does not change, the subscriber will not be notified.
(意訳)キャッシュが変更されなければ、変更は通知されないことに注意。
Angular 7でテスト用のアプリケーションを生成して、Apollo ClientをラップしたAWSAppSyncSDKを使ってreadQuery
・watchQuery
あたりを試してみる。
$ ng new AngularApolloSample
$ cd AngularApolloSample
# AWS AppSync JavaScript SDKをインストール
$ npm install --save aws-appsync graphql-tag
ディレクトリ構造は以下のようになった。
$ tree src
src
├── app
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ └── app.module.ts
├── assets
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── main.ts
├── polyfills.ts
├── styles.css
├── test.ts
├── tsconfig.app.json
├── tsconfig.spec.json
└── typings.d.ts
AppSyncのマネジメントコンソールから作成。適当にPostモデルを作成する。
ngOnInit() {
this.client = new AWSAppSyncClient({
url: 'https://XXXXXXXXXXX.appsync-api.ap-northeast-1.amazonaws.com/graphql',
region: 'ap-northeast-1',
auth: {
type: AUTH_TYPE.API_KEY,
apiKey: 'XXXXXXXXXXXXX',
}
});
}
import { Component, OnInit } from '@angular/core';
import AWSAppSyncClient, { AUTH_TYPE } from 'aws-appsync';
import { v4 as uuid } from 'uuid';
import * as queries from '../graphql/queries';
import * as mutations from '../graphql/mutations';
interface Post {
id: string;
content: string;
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
client;
content = '';
posts: Post[] = [];
posts2: Post[] = [];
ngOnInit() {
this.client = new AWSAppSyncClient({
url: 'https://XXXXXXXXXXXXXXXXXXXXX.appsync-api.ap-northeast-1.amazonaws.com/graphql',
region: 'ap-northeast-1',
auth: {
type: AUTH_TYPE.API_KEY,
apiKey: 'XXXXXXXXXXXXXXXXXXXXX',
}
});
this.setWatchQuery();
this.load();
}
onCreateClicked() {
this.client.hydrated().then(client => {
client.mutate({
mutation: mutations.createPost,
variables: {
input: {
content: this.content,
}
},
optimisticResponse: () => ({
createPost: {
id: uuid(),
content: this.content,
__typename: 'Post'
}
}),
}).then(() => {
this.content = '';
});
});
}
load() {
this.client.hydrated().then(client => {
client.query({
query: queries.listPosts,
fetchPolicy: 'network-only',
}).then(data => {
this.posts = data.data.listPosts.items;
});
});
}
setWatchQuery() {
this.client.hydrated().then(client => {
client.watchQuery({
query: queries.listPosts,
fetchPolicy: 'cache-and-network',
}).subscribe(data => {
console.log('subscribe', data);
this.posts2 = data.data.listPosts.items;
});
});
}
}
fetchPolicy
で動作が異なることはわかったfetchPolicy
に指定できるタイプによって動作がどう変わるかがわからない。readQuery
・watchQuery
のユースケースがわからない。