javascript - Angular 2 : Change detection inside observable

标签 javascript typescript angular angular-cli angular2-changedetection

刚刚我用 Angular2 RC3(使用 Angular-CLI)尝试了我的第一个应用程序,但我迷失了......

我对变量 word 的“变化检测”有疑问。我在 Observable 的 subscribe 方法中更新了 word 变量,但没有检测到任何变化。

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 中执行,但什么也没有。

我做错了什么?

非常感谢。


额外:

我与 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 zone 修补。

解决方法是使用 zone.run(...) 明确地强制执行回到 Angulars 区域:

@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)),请相应地调整代码。我只是为每个假设了一个参数。

这种方法的优点是该服务的用户不必采取额外措施。

关于javascript - Angular 2 : Change detection inside observable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38100128/

相关文章:

typescript - 类验证器使用 createQueryBuilder 意外触发验证

json - Angular 2 将 JSON 对象解析为 Angular 类

javascript - 如何在 Angular 8+ 中使用 Panzoom javascript?

javascript - 字符串中子字符串出现的次数 [Javascript]

javascript - jQuery 全局变量

javascript - 当Materializecss模式在移动浏览器上打开时如何防止背景滚动?

javascript - NestJS TypeORM 导入解决方案

javascript - 完整日历加载事件源,天数显示的位置不正确

typescript - 使用 typescript 中的变量访问对象键

angular - 类型错误 : Cannot read property 'snapshot' of undefined failure while performing unit testing in angular2