如何在 Angular 4 和 IONIC 3 中使用 $apply 和 $digest?

How to $apply and $digest in Angular 4 and IONIC 3?

我正在尝试在 IONIC 3 中创建应用程序,但它似乎无法正确刷新视图。

我记得 $apply 和 $digest 会在 Angular 1X 中解决此类问题。

在 Angular 4 中是如何完成的?

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { BLE } from '@ionic-native/ble';

@Component({
  selector: 'page-led',
  templateUrl: 'led.html'
})
export class LEDPage {

  constructor(public navCtrl: NavController, private ble: BLE) {
    this['myCount'] = 0;
    this['valor'] = 0;
    this['messages'] = [];
    this['service_id'] = "19B10010-E8F2-537E-4F6C-D104768A1214";
    this.setMessage("Constructor: Begin!");
    this['ble'] = ble;
    this['ComandoTXT'] = "FIND BLYNK";
    this['targetDevice'] = {};
  }
  
  public Command(){
    if(this['ComandoTXT']==="FIND BLYNK") {
      this.findBlynk();
    }
    
    if(this['ComandoTXT']=== "CAMBIAR LED"){
      //this.txData();
      this.setMessage("CAMBIAR LED txData DISABLEd");
    }
  }
  
  public findBlynk(){
      this.setMessage("SCAN: Begin!");
      this['ComandoTXT'] = "Scanning...";

      let  ble = this['ble'];
      
      this.setMessage("SCAN: BLE ENABLE!");
      ble.enable();
      
      this.setMessage("SCAN: Setting Interval...");
      this['intervalHandle'] = setInterval(() => { // SET AN INTERVAL THAT RUNS EVERY 3 Seconds
        this.setMessage("INTERVAL: BLE SCAN...");
        //https://ionicframework.com/docs/native/ble/ 
        ble.scan([], 2 /*seconds (0) */).subscribe( data => { //DO SCAN DURING 1 SECOND
          this.setMessage("SCAN SUBSCRIBER: " + data['id'] + ' | ' + data['name'] + ' | ' + data['rssi']);
          if(data['name']=="Blynk"){
            this.setMessage("SCAN SUBSCRIBER: BLYNK FOUND! STOPPED SCANNING!");
            clearInterval(this["intervalHandle"]);
            this["targetDevice"] = data;
            this["ComandoTXT"] = "CAMBIAR LED";

            let idx = 0;
            while(idx<10000){
              this["test"] = idx;
              idx ++;
            }
          }
        });
      },2100);//END OF INTERVAL DEFINITION
    }  
  
  /*
  public findBlynk(){
    this.setMessage("findBlynk: BEGIN...");
    this['ComandoTXT'] = "Buscando...";
    this.setMessage("findBlynk: BLE ENABLE...");
    this['ble'].enable();
    this.setMessage("findBlynk: encontrar()...");

    this.ble.scan([],500).subscribe(deviceData=>{
      this.setMessage("SUBSCRIBER: Found Device...");
      let deviceMessage = deviceData.id + ":" + deviceData.name + "(" + deviceData.rssi + ")";
      this.setMessage(deviceMessage);
      
      if(deviceData.name == "Blynk"){
        this.setMessage("BLYNK FOUND!");
        this["ComandoTXT"] = "CAMBIAR LED";
        this['dispositivo'] = deviceData;  
        
        this.ble.stopScan().then(() => {
          this.setMessage('SCANNING STOPPED!');
        });
        
      } else {
        //setTimeout(()=>{this.findBlynk();},500);
      }
    
    }, error=>{
      this.setMessage("BLE SCAN ERROR");
      this.setMessage(error.message);
      setTimeout(()=>{this.findBlynk();},1000);
    });
  }
  
  public txData(){
    this.setMessage("txData: BEGIN! Doing ble connect...");
    let id = this['deviceData'].id;
    this.ble.connect(id).subscribe(datos=>{
      this.setMessage("BLE CONNECT SUBSCRIBE: BEGIN. Doing ble write...");
      this.ble.write(id,this['service_id'],this['service_id'],this['valor'].buffer).then(()=>{
        this.setMessage("BLE WRITE THEN!");
        this['valor'] = (this['valor'] + 1) % 2;
        this.ble.disconnect(id);
      },(error)=>{
        this.setMessage("BLE Write ERROR!");
      });
    },error=>{
      this.setMessage("BLE Connect ERROR!");
    });
  }
  */
/*
  
  public conectar(id){
    this.ble.connect(id).subscribe(datos=>{
      this.escribir(id);
    },error=>{
      this.encontrar();  
    });
  }

  public escribir(id){

  }
  
*/
  public setMessage(message){
    this['myCount'] ++;
    message = this['myCount'] + ':' + message;
    this['messages'].unshift(message);
  }

}
<ion-header>
  <ion-navbar>
    <ion-title>LED </ion-title>
    <button ion-button (click)="Command()">{{ComandoTXT}}</button>
  </ion-navbar>
</ion-header>
<ion-content padding>
  <p>LED  Messages: ({{myCount}} | {{test}})</p>
  <hr />
  <p *ngFor="let message of messages">{{message}}</p>
</ion-content>

您可以使用 LifeCycle::tick() 方法来完成。见下面代码

import {Component, LifeCycle, NgZone} from 'angular2/angular2'

@Component({
  selector: 'my-app',
  template: `
    <div>
      Hello world!!! Time: {{ time }}.
    </div>
  `
})
export class App {
  time: number = 0;

  constructor(lc: LifeCycle, zone: NgZone) {
    zone.runOutsideAngular(() => {
      setInterval(() => {
        this.time = Date.now();

        lc.tick(); // comment this line and "time" will stop updating
      }, 1000);
    })
  }
  doCheck() {
    console.log('check', Date.now());
  }
}

基本上问题是我不明白如何在 Typescript 中调用 ApplicationRef 对象。

所以我在 .ts 文件顶部的第 4 行添加了“import { ApplicationRef } from '@angular/core'”,然后在第 28 行的构造函数私有“applicationRef : ApplicationRef”中注入它,最终调用“this.applicationRef.tick();" 在回调的末尾,例如第 81 行。

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { BLE } from '@ionic-native/ble';
import { ApplicationRef } from '@angular/core'

@Component({
  selector: 'page-led',
  templateUrl: 'led.html'
})


export class LEDPage {

  /**
   * Constants that we will use around the controller
   */
  public constants  = {
      CMD_FIND_ANGU:"FIND ANGU",
      CMD_STOP_SCAN:"Scanning... (Click to Stop)",
      CMD_TOGGLE_LED:"CAMBIAR LED",
      ON:"ON",
      OFF:"OFF"
    };

  /**
   * Constructor for the controller. Everything begins here.
   */
  constructor(public navCtrl: NavController, private ble: BLE, private applicationRef : ApplicationRef ) {
    this['messages'] = [];
    this['value'] = "ON FIRST TIME";
    this['service_id'] = "19B10010-E8F2-537E-4F6C-D104768A1215";
    this['characteristic_id'] = "19B10011-E8F2-537E-4F6C-D104768A1215";
    this['ble'] = ble;
    this['ComandoTXT'] = this.constants.CMD_FIND_ANGU;
    this['targetDevice'] = {};
    this.setMessage("Constructor: Begin!");
    this["applicationRef"] = applicationRef;
  }
  
  /**
   * This is triggered when the button is clicked.
   */
  public Command(){
    this.setMessage("COMMAND RECEIVED!");
    this.setMessage(this["ComandoTXT"]);
    if(this['ComandoTXT']===this.constants.CMD_FIND_ANGU) {
      this['ComandoTXT'] = this.constants.CMD_STOP_SCAN;
      this.findANGU();
    } else if (this['ComandoTXT']===this.constants.CMD_STOP_SCAN) {
      this.setMessage("Command: STOPING SCAN...");
      clearInterval(this['intervalHandle']);
      this['ComandoTXT'] = this.constants.CMD_FIND_ANGU;
    } else if(this['ComandoTXT']=== this.constants.CMD_TOGGLE_LED){
      this.setMessage("ComandoTXT = CAMBIAR LED: Calling txData()");
      this.txData();    
    }
  }
  
  /**
   * This searches for ANGU in the AIR using SCAN technique.
   */
  public findANGU(){
      this.setMessage("SCAN: Begin!");
      let  ble = this['ble'];
      
      this.setMessage("SCAN: BLE ENABLE!");
      ble.enable();
      
      this.setMessage("SCAN: Setting Interval...");
      this['intervalHandle'] = setInterval(() => { // SET AN INTERVAL THAT RUNS EVERY 3 Seconds
        this.setMessage("INTERVAL: BLE SCAN...");
        //https://ionicframework.com/docs/native/ble/ 
        ble.scan([], 2 /*seconds (0) */).subscribe( data => { //DO SCAN DURING 1 SECOND
          this.setMessage("SCAN SUBSCRIBER: " + data['id'] + ' | ' + data['name'] + ' | ' + data['rssi']);
          if(data['name']=="COMANDO LED"){
            this.setMessage("SCAN SUBSCRIBER: ANGU FOUND! STOPPED SCANNING!");
            clearInterval(this["intervalHandle"]);
            this["targetDevice"] = data;
            this["ComandoTXT"] = this.constants.CMD_TOGGLE_LED;
          }
          this.applicationRef.tick();
        });
      },2100);//END OF INTERVAL DEFINITION
    }  

  /**
   * This transmits data to the selected ANGU device  
   */  
  public txData(){
    this.setMessage("txData: BEGIN! Doing ble connect...");
    
    let id = this['targetDevice'].id;
    this.setMessage(id);
    
    this.ble.connect(id).subscribe(datos=>{
      this.setMessage("BLE CONNECT SUBSCRIBE: BEGIN. Doing ble write..." + this["value"]);

      this.ble.write(this['targetDevice'].id, this['service_id'],this['characteristic_id'], this.stringToBytes(this["value"]) ).then(()=>{
        this.setMessage("BLE WRITE THEN:" + this["value"]);
        if(this["value"]==this.constants.ON){
          this["value"] = this.constants.OFF;
        } else {
          this["value"] = this.constants.ON;
        }
        this.ble.disconnect(id);
        this.applicationRef.tick();
      },(error)=>{
        this.setMessage("BLE Write ERROR!");
        this.setMessage(error);
        this.ble.disconnect(id);
      });
    },error=>{
      this.setMessage("BLE Connect ERROR!");
      this.setMessage(error.message);
    });
  }
  
  /**
   * Adds message to the history on screen
   */
  public setMessage(message){
    var count = this['messages'].length;
    message = count + ':' + message;
    this['messages'].unshift(message);
    this.applicationRef.tick();
  }

  // ASCII only
  public stringToBytes(string) {
     let array = new Uint8Array(string.length);
     for (let i = 0, l = string.length; i < l; i++) {
         array[i] = string.charCodeAt(i);
      }
      return array.buffer;
  }
  
  // ASCII only
  public bytesToString(buffer) {
      return String.fromCharCode.apply(null, new Uint8Array(buffer));
  }
}
<ion-header>
  <ion-navbar>
    <ion-title>LED </ion-title>
    <button ion-button (click)="Command()">{{ComandoTXT}}</button>
  </ion-navbar>
</ion-header>
<ion-content padding>
  <p>LED  Messages: ({{myCount}} | {{test}})</p>
  <hr />
  <p *ngFor="let message of messages">{{message}}</p>
</ion-content>