首页 > 解决方案 > 更改后文本框未立即更新

问题描述

我是 Angular 的绝对初学者,目前正在开发一个通过 http 访问服务的项目。用户可以将文件发送到服务(使用 HttpClient)。进程更新(使用 SignalR)应显示在文本区域中。更新正确地进入我的组件。控制台日志立即显示。但是 textarea 仅在一切完成后才更新(过程完成后,从服务中获取结果)。

我的组件 HTML 以显示流程更新:

    <textarea name="status" id="status" 
        [ngModel]="status | async"              // binding to property of StatusComponent
        #name="ngModel"
        disabled>
    </textarea>

我的组件 TS 以显示流程更新:

export class StatusComponent implements OnInit {
  public status: Observable<string> = new Observable<string>(); // binding to view
  private states: string[] = []; // store states as list

  constructor(private protocol: ProtocolService) { }

  ngOnInit(): void {
    this.protocol.getStatus()
      .pipe(share())
      .subscribe(state => {
        console.log("update state: " + state);   // is shown in time
        this.states.push(state);
        this.status = of(this.states.join("\n")); // is shown when all processes are finished
      }
    );
  }
}

存储状态的我的协议服务:

@Injectable({providedIn: 'root'})
export class ProtocolService {
  private status: Subject<string> = new Subject<string>();

  constructor() { }

  public getStatus(): Observable<string> {
    return this.status.asObservable()
    .pipe(share());
  }

  public setStatus(state: string){
    this.status.next(state);
    this.addToProtocol(state);
  }
}

在绑定到我的输入表单的另一个组件中,请求被发送到 http 服务并处理来自 signalr 的回调。它还在 ProtocolService 中设置状态。这里只是 TS 的摘录:

export class ProcessComponent implements OnInit {
constructor(
      private service: ProcessService,
      private broadcast: SignalRService,
      private protocol: ProtocolService
      ) 
   }

  public connect() {
    this.broadcast.startConnection(this.url);
    this.broadcast.addDocumentStatusListener(this.onDocumentStatusUpdate.bind(this)); // get updates from signalr
  }

  public process() {
    this.service.process(this.url, this.selectedProject, this.file)
    .subscribe((res) => { });
  }

  private onDocumentStatusUpdate(dto: DocumentStateDto) {
      const entry: string = ClassificationState[state];
      this.protocol.setStatus(entry);
  }

}

我的流程服务:

@Injectable({providedIn: 'root'})
export class ProcessService {
public process(url:string, project: string, file: File): Observable<ProcessDto> {
    const formData: FormData = new FormData();
    formData.append(file.name, file, file.name);

    const request:string = this.buildRequest(url, this.uploadRequest);
    var result = this.client.post<any>(request, formData)
      .pipe(
        share(), 
        catchError(this.handleError("process", null)));
    return result;
  }
}

我的 SignalR 服务:

@Injectable({providedIn: 'root'})
export class SignalRService {
    private hubConnection?: signalR.HubConnection;

    public startConnection(url: string) {
        this.hubConnection = new signalR.HubConnectionBuilder()
            .withUrl(url)
            .withAutomaticReconnect()
            .build();
        this.hubConnection?.start()
      .catch((err) => console.log('Error while starting connection: ' + err));
    }

public addDocumentStatusListener(DocumentStatusCallback: Function) {
    this.addBroadcastDocumentStatusListener(DocumentStatusCallback);
}

private addBroadcastDocumentStatusListener(callback: Function) {
    this.hubConnection?.off('BroadcastDocumentStatus');
    this.hubConnection?.on('BroadcastDocumentStatus', (guid, processStatus, documentStatus) => {
        var dto: DocumentStateDto = {Guid: guid, ProcessState: processStatus, DocumentState: documentStatus};
        callback(dto);
    });
}

我想知道为什么我的控制台日志会立即输出,而 textarea 最终只会更新。我在firefox和chrome上测试过。此外,我测试了使用字符串变量而不是 Observable 并使用输入(类型文本)而不是 textarea,但行为始终相同。我在一个小项目中隔离了这个问题。当我使用超时回调更新文本区域时,文本会立即显示。当 SignalR 发挥作用时,文本框输出会延迟。我是否以不好的方式使用 SignalR,以至于我阻止了文本框输出?

如果您需要更多信息或代码,请不要犹豫询问。我感谢任何有助于更好地理解这个问题的帮助。

最好的,BerkelBits

标签: angularhttpobservablesignalrngmodel

解决方案


推荐阅读