Aurelia BindingEngine propertyObserver不会触发

问题描述 投票:0回答:1

我有一个Aurelia文件上传控制器,我想观察添加到数组progress的任何对象的uploadedFiles属性。首先,我的HTML模板如下所示:

<input type="file" name="files" files.bind="fileList" multiple change.delegate="fileSelected($event)" />

这是控制器(简化)。当用户选择文件时,方法fileSelected被触发。

import {BindingEngine, inject} from 'aurelia-framework';
import {HttpService} from '../../services/http-service';
import {UploadedFile} from '../../models/uploaded-file';

@inject(BindingEngine)
export class FileUploader {
  httpClient: HttpService;
  fileList: FileList;
  uploadedFiles: UploadedFile[];

  constructor(bindingEngine) {
    this.bindingEngine = bindingEngine;
    this.httpClient = new HttpService();
    this.uploadedFiles = [];
  }

  fileSelected(): void {
    if (this.fileList) {
      // Convert the FileList object into an array of UploadedFile objects because the Aurelia template engine cannot iterate over a 'FileList' object with 'repeat.for'.
      for (let i = 0; i < this.fileList.length; i++) {
        let file = this.fileList.item(i);
        let uploadedFile = new UploadedFile();
        uploadedFile.file = file;

        // Subscribe to changes of the 'progress' property of every UploadedFile.
        uploadedFile.subscription = this.bindingEngine
          .propertyObserver(uploadedFile, 'progress')
          .subscribe((newValue, oldValue) => {
            console.log('Progress changed from ' + oldValue + ' to ' + newValue);
          });

        this.uploadedFiles.push(uploadedFile);

        // Start off the file upload itself.
        this.httpClient.uploadRequest('files', file, uploadedFile.updateProgress)
          .then((httpResponse) => {
            // File uploaded successfully!
          });
      }
    }
  }
}

我这样做是因为进度更新来自外部事件,因此从控制器到模板的绑定不是开箱即用的(因为出于性能原因不会观察到每个对象)。

这是UploadedFile类:

export class UploadedFile {
  file: File;
  uploaded: boolean;
  totalBytes: number;
  uploadedBytes: number;
  progress: number;
  subscription: any;

  constructor() {
    this.uploaded = false;
    this.progress = 0;
  }

  updateProgress(event: ProgressEvent) {
    this.totalBytes = event.total;
    this.uploadedBytes = event.loaded;

    this.progress = this.uploadedBytes / this.totalBytes * 100;
    console.log('Progress is ' + this.progress + ' %.');
  }
}

以下是上传请求的样子(请注意withProgressCallback行):

import {HttpClient} from 'aurelia-http-client';

export class HttpService {
  backendUrl: string;
  httpClient: HttpClient;

  constructor() {
    // ...
  }

  uploadRequest(url: string, file: File, progressCallback: any): Promise<any> {
    let formData = new FormData();
    formData.append('file', file);

    return this.httpClient.createRequest(url)
      .asPost()
      .withContent(formData)
      .withCredentials(true)
      .withProgressCallback(progressCallback) // This adds the progress callback.
      .send();
  }
}

现在显然我做错了,因为属性更改事件永远不会触发,即使我可以在UploadedFile类的浏览器控制台中看到进度更新。

有人能告诉我propertyObserver订阅有什么问题吗?

javascript file-upload aurelia aurelia-binding
1个回答
1
投票

在上传进度时,您需要确保它可以通过浏览器进行跟踪。其次,你在uploadRequest中的HttpService不会保留执行上下文,这意味着updateProgress将不会被调用UploadedFile类的正确实例。可能你需要做这样的事情:

this.httpClient.uploadRequest('files', file, () => uploadedFile.updateProgress() })
      .then((httpResponse) => {
        // File uploaded successfully!
      });
© www.soinside.com 2019 - 2024. All rights reserved.