【发布时间】:2017-07-28 09:21:27
【问题描述】:
我正在尝试从 Angular 2 服务中加载脚本 https://apis.google.com/js/api.js?onload=initGapi 以调用 Google API,但每当我尝试在脚本完成加载和初始化时返回一个值时,@987654322 @pipe 不想将值呈现给模板。
我正在使用EventEmitter,它在gapi.load() 和gapi.client.init 完成时触发,并且在组件中订阅了可观察对象。异步管道似乎不想读取该值,直到我单击同一组件中的一个按钮(并且可能触发更改检测)。当我使用来自ApplicationRef 的tick() 时,强制组件内的更改检测不起作用。
加载 Google API 的服务如下:
google-api.service.ts
import { Injectable, EventEmitter } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { User, Client } from '../../+home/models';
declare var gapi: any;
@Injectable()
export class GoogleApiService {
CLIENT_ID: string = '....apps.googleusercontent.com';
DISCOVERY_DOCS: string[] = ["https://www.googleapis.com/discovery/v1/apis/admin/directory_v1/rest"];
SCOPES = 'https://www.googleapis.com/auth/admin.directory.user.readonly';
authEmitter: EventEmitter<boolean> = new EventEmitter();
constructor() {
window['initGapi'] = (ev) => {
this.handleClientLoad();
};
this.loadScript();
}
loadScript() {
let script = document.createElement('script');
script.src = 'https://apis.google.com/js/api.js?onload=initGapi';
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
}
handleClientLoad() {
gapi.load('client:auth2', this.initClient.bind(this));
}
initClient() {
gapi.client.init({
discoveryDocs: this.DISCOVERY_DOCS,
clientId: this.CLIENT_ID,
scope: this.SCOPES
}).then(() => {
this.authEmitter.emit(true);
});
}
get gapi(): Observable<any> {
return this.authEmitter.map(() => 'hello world');
}
}
以及从服务中读取的组件
app.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { GoogleApiService } from '../../+core/services';
@Component({
template: `
What does the service say?
{{ api$ | async }}
<button (click)="click()">Button</button>`
})
export class InviteEmployeesContainer implements OnInit {
api$: Observable<string>;
constructor(private gApiService: GoogleApiService) {}
ngOnInit() {
this.api$ = this.gApiService.gapi;
this.gApiService.gapi.subscribe((result) => {
console.log(result);
});
}
click() {
console.log('clicked');
}
}
生成的页面打印出字符串 What does the service say? 并有一个按钮,但在我单击按钮之前不会打印文本 hello world,这不是所需的行为,它应该立即在页面上可见.
此外,当我使用this.gApiService.gapi.subscribe 订阅和登录控制台时,它会在我期望的时候记录hello world。
有谁知道当authEmitter 触发事件时,我如何使用异步管道让hello world 打印到页面。
【问题讨论】:
-
您是否尝试将其作为吸气剂直接返回
get api$() { return this.service.gapi }。您也可以尝试使用ChangeDetectorRef来强制进行更改检测。 -
直接返回是不好的,因为我不希望组件在它准备好之前使用它,它需要做2个网络请求并运行
init才能使用它,因此我为什么我'正在使用一个可观察的。我会尝试强制进行更改检测,但我认为这不是一个实用的长期解决方案,因为这通常是我希望可观察对象能够处理的问题。 -
你知道你可以在
async管道准备好之前订阅它,组件将在它发出数据后立即开始使用它。 (正如我所见,您只是在加载后才发出新项目) -
@cyrix 我知道,但这不是我真正的用例,只是重现问题所需的最少代码量,因为我的实际实现比这更复杂。
-
我遇到了同样的问题,并得出了与这个问题的唯一答案相同的解决方案。我很想知道这个问题背后的原因。
标签: angular google-api angular2-observables angular2-changedetection google-api-js-client