使用Angular调用GitHub的GraphQL API

我会记录一个初学者在Angular中使用GitHub的GraphQL的步骤。我们将使用Apollo。

这次的GitHub仓库是ovrmrw/angular-apollo-github-graphql。

安装angular-cli。

$ npm i -g angular-cli

创建一个新的Angular项目。

$ ng new new-project

根据通信环境和机器配置的不同,ng new可能需要相当长的时间,甚至可以洗一个澡的时间。

安装 Apollo

阿波罗初始化文件

$ npm install apollo-client angular2-apollo graphql-tag --save

使用Apollo可以在Angular中访问GraphQL服务器并获取数据。
在这个示例中,我们将尝试访问GitHub的GraphQL API。

进行GitHub的设置

就个人而言,我在这里遇到了最大的困难。从结论来看,需要仔细阅读这里。→ 访问 GraphQL

首先

你必须已经注册了提前访问计划。

听说了。请遵循指示。
接下来

你需要一个具有正确范围的OAuth令牌。

请阅读“生成OAuth令牌”部分,并按照指示进行操作。

然后使用获得的Token。

把 GitHub Token 包含在项目中

config.secret.default.ts 复制并创建 config.secret.ts 文件。
然后修改其中内容。

export const githubToken = 'your_github_token';

我會按照這樣的方式進行編輯。

当然的事情是,应该注意确保这个文件不会被推送到GitHub仓库中。

编辑app.module.ts

以下是app.module.ts的完整代码。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import ApolloClient, { createNetworkInterface } from 'apollo-client';
import { ApolloModule } from 'angular2-apollo';

import { AppComponent } from './app.component';
import { AppService } from './app.service';
import { githubToken } from '../../config.secret';
import { StoreModule } from './store';


const networkInterface = createNetworkInterface('https://api.github.com/graphql');
networkInterface.use([{
  applyMiddleware(req, next) {
    if (!req.options.headers) {
      req.options.headers = {};
    }
    req.options.headers['authorization'] = `bearer ${githubToken}`;
    next();
  }
}]);
const client = new ApolloClient({ networkInterface });


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    ApolloModule.withClient(client),
    StoreModule,
  ],
  providers: [AppService],
  bootstrap: [AppComponent]
})
export class AppModule { }

因为有点混乱,我们来提取与Apollo相关的部分。

import ApolloClient, { createNetworkInterface } from 'apollo-client';
import { ApolloModule } from 'angular2-apollo';

import { githubToken } from '../../config.secret';


const networkInterface = createNetworkInterface('https://api.github.com/graphql');
networkInterface.use([{
  applyMiddleware(req, next) {
    if (!req.options.headers) {
      req.options.headers = {};
    }
    req.options.headers['authorization'] = `bearer ${githubToken}`;
    next();
  }
}]);
const client = new ApolloClient({ networkInterface });


@NgModule({
  imports: [ApolloModule.withClient(client)],  
})
export class AppModule { }

我通过创建networkInterface,在ApolloModule中包含生成的ApolloClient的内容,使代码更加清晰。
我稍微明白之前的GitHub令牌是如何在请求头中被包含的。

尝试调用GraphQL API(创建app.service.ts)

阿波罗查询文档

参考Apollo的文件,创建一个Service。因为我现在非常喜欢Redux,所以我会创建一个流程,将API的返回值通过dispatcher发送到Store中。由于apollo.watchQuery的返回值是扩展的Observable,所以熟悉RxJS也是很有好处的。通过使用take(1),确保每次都完成并避免内存泄漏。

import { Injectable } from '@angular/core';
import { Angular2Apollo } from 'angular2-apollo';
import gql from 'graphql-tag';

import { environment } from '../environments/environment';
import { Dispatcher, Action, RequestViewerAction, ViewerState } from './store';


const CurrentViewerQuery = gql`
  query {
    viewer {
      name
      login
    }
  }
`;


@Injectable()
export class AppService {
  constructor(
    private dispatcher$: Dispatcher<Action>,
    private apollo: Angular2Apollo,
  ) { }


  requestViewer(): void {
    console.time('requestViewer');
    this.apollo
      .watchQuery({ query: CurrentViewerQuery })
      .take(1)
      .subscribe(result => {
        if (!environment.production) {
          console.log('result:', result);
        }
        const viewer = result.data.viewer as ViewerState;
        this.dispatcher$.next(new RequestViewerAction(viewer));
      }, err => console.error(err), () => console.timeEnd('requestViewer'));
  }

}

在组件中接收状态(编辑app.component.ts文件)

由于Redux的存在,组件在调用动作后需要接收状态。

import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Observable } from 'rxjs/Rx';

import { AppService } from './app.service';
import { Store, AppState } from './store';


@Component({
  selector: 'app-root',
  template: `
    <h1>{{title}}</h1>
    <pre>{{state | async | json}}</pre>
    <div>
      <button (click)="requestViewer()">Request Viewer</button>
    </div>
  `,
  styleUrls: ['./app.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
  title = 'app works!';

  constructor(
    private service: AppService,
    private store: Store,
  ) { }


  requestViewer(): void {
    this.service.requestViewer();
  }

  get state(): Observable<AppState> { return this.store.getState(); }

}

处理的步骤如下。

    1. 通过调用requestViewer()来调用Service的Action。

通过get state()作为Observable接收更新后的State。
通过{{state | async | json}}使用AsyncPipe接收state的模板。
视图会被更新。

确认Apollo正在缓存数据。

我们来启动应用程序吧。

$ npm start

在浏览器中打开http://localhost:4200/。

当您点击“请求查看者”按钮后,可以确认您的名字是否会显示出来。

不管点击多少次,显示都不会改变,但请使用开发者工具监视网络。你会发现在第二次及以后没有发生HTTP请求。

太酷了!

顺便提一下

this.apollo.watchQuery({ query: CurrentViewerQuery })

將…

this.apollo.watchQuery({ query: CurrentViewerQuery, forceFetch: true })

如果存在缓存,每次都强制获取。有关缓存机制的详细信息,请参考《GraphQL概念可视化》

关于Redux部分

Redux的构建是通过RxJS完成的。源代码在这里。→ src/app/store

广告
将在 10 秒后关闭
bannerAds