Angular2:可观察内的变化检测 [英] Angular2: Change detection inside observable
问题描述
我刚刚使用 Angular2 RC3(使用 Angular-CLI)尝试了我的第一个应用程序,但我对此感到迷茫......
Just I tried my first app with Angular2 RC3 (Using Angular-CLI) and I'm lost with this...
我对变量 word
的更改检测"有问题.我更新了 Observable 的 subscribe
方法中的 word
变量,但没有检测到任何变化.
I have a problem with "Change detection" of variable word
. I update the word
variable inside the subscribe
method of Observable, but no changes detected.
app.component.ts
import { Component, Inject, OnInit } from '@angular/core';
import { VoiceRecognitionService } from './voice-recognition.service';
@Component({
moduleId: module.id,
selector: 'app-root',
template: `<h1>{{word}}</h1>`, // => No prints any update
providers: [VoiceRecognitionService],
styleUrls: ['app.component.css']
})
export class AppComponent implements OnInit {
private voice: VoiceRecognitionService;
public word: string = '';
constructor( @Inject(VoiceRecognitionService) voiceRecognition: VoiceRecognitionService) {
this.voice = voiceRecognition;
}
ngOnInit() {
this.voice.record('ca')
.subscribe(word => {
console.log(word); // => Is printing well the new word
this.word = `${word}...`; // => No changes detected
});
}
}
我记得在 Angular 1 中使用了 $scope.$apply
来处理类似的情况,我在 Angular2 中搜索了同样的内容,我找到了 NgZone.run
,我试图在 NgZone.run
内执行,但什么也没有.
I remember in Angular 1 the use of $scope.$apply
for similar cases and I search the same for Angular2 and I found NgZone.run
, I tried to execute inside NgZone.run
, but nothing.
我做错了什么?
非常感谢.
我与 Observable 分享我的服务:
I share my service with the Observable:
voice-recognition.service.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
export interface IWindow extends Window {
webkitSpeechRecognition: any;
}
@Injectable()
export class VoiceRecognitionService {
constructor() {
/* void */
}
/**
* Record
* @param {string} language - Language of the voice recognition
* @returns {Observable<string>} - Observable of voice converted to string
*/
record(language: string): Observable<string> {
return Observable.create((observer) => {
const { webkitSpeechRecognition }: IWindow = <IWindow>window;
const recognition = new webkitSpeechRecognition();
recognition.onresult = (e) => observer.next(e.results.item(e.results.length - 1).item(0).transcript);
recognition.onerror = observer.error;
recognition.onend = observer.completed;
recognition.continuous = true;
recognition.interimResults = true;
recognition.lang = language;
recognition.start();
});
}
}
推荐答案
我假设 webkitSpeechRecognition
API 没有被 Angulars 区域修补.
I assume the webkitSpeechRecognition
API is not patched by Angulars zone.
要解决使用 zone.run(...)
强制执行回 Angulars zone 明确:
To work around use zone.run(...)
to force the execution back into Angulars zone explicitely:
@Injectable()
export class VoiceRecognitionService {
constructor(private zone:NgZone) {
/* void */
}
/**
* Record
* @param {string} language - Language of the voice recognition
* @returns {Observable<string>} - Observable of voice converted to string
*/
record(language: string): Observable<string> {
return Observable.create((observer) => {
const { webkitSpeechRecognition }: IWindow = <IWindow>window;
const recognition = new webkitSpeechRecognition();
recognition.onresult = (e) => this.zone.run(() => observer.next(e.results.item(e.results.length - 1).item(0).transcript));
recognition.onerror = (e) => this.zone.run(() => observer.error(e));
recognition.onend = (e) => this.zone.run(() => observer.completed(e));
recognition.continuous = true;
recognition.interimResults = true;
recognition.lang = language;
recognition.start();
});
}
}
如果回调需要不同数量的参数((e)
),请相应地调整代码.我只是假设每个参数一个.
If the callbacks need a different number of parameters ((e)
) please adjust the code accordingly. I just assumed one parameter for each.
这种方法的优点是该服务的用户不必采取额外的措施.
The advantage of this approach is that the users of this service don't have to take additional measures.
这篇关于Angular2:可观察内的变化检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!