javascript 自定义窗口,FileReader方法在Angular 区域外执行

lmyy7pcs  于 2023-02-11  发布在  Java
关注(0)|答案(1)|浏览(89)

将离子/Angular 项目从Cordova迁移到Capacitor后,我必须覆盖默认window.FileReader,以便能够以以下方式执行onload()方法(https://github.com/ionic-team/capacitor/issues/1564):

constructor(
    appRef: ApplicationRef
  ) {
    class IonicFileReader extends window.FileReader {
      constructor() {
        super();

        // solution 3 - not working
        // this.onload = (e) => {
        //   this.onload(e);
        //   appRef.tick(); console.log('tick');
        // }

        // Solution 4 - working
        // setTimeout(() => {
        //   appRef.tick(); console.log('tick ctor');
        // }, 1000);

        // solution 5 - not working
        // super.onload = (e) => {
        //   this.onload(e);
        //   appRef.tick();
        //   console.log('tick');
        // };

        // solution 8 - not working
        // super.onload = (e) => {
        //   appRef.tick(); console.log('tick');
        //   super.onload.apply(this.onload);
        // };

        const zoneOriginalInstance = (this as any)[
          '__zone_symbol__originalInstance'
        ];
        return zoneOriginalInstance || this;
      }

      // solution 1 - not working
      // onload = (e) => {
      //   this.onload(e);
      //   appRef.tick(); console.log('tick');
      // }

      // solution 7 - not working
      // onload = function(e) {
      //   appRef.tick(); console.log('tick');
      //   return this.onload(e);
      // }

      // solution 9 = not working
      // refresh = function() {
      //   appRef.tick();
      // }
      // (window.FileReader as any).refresh();
    }

    // solution 6 - not working
    // window.FileReader.prototype = new IonicFileReader();
    // window.FileReader.prototype.onload = function(ev) {
    //   this.onload(ev);
    //   appRef.tick(); console.log('tick prototype');
    // }

    // solution 2 - not working
    // window.FileReader.prototype = IonicFileReader.prototype;

    window.FileReader = IonicFileReader;
  }

我在AppModuleconstructor中重写了它,以便通过ApplicationRef来调用更改检测机制。不幸的是,没有解决方案(除了解决方案4,这是不可接受的)起作用。
应在此函数调用期间启动更改检测:

function blobToText(blob: any): Observable<string> {
    return new Observable<string>((observer: any) => {
        if (!blob) {
            observer.next("");
            observer.complete();
        } else {
            let reader = new FileReader();
            reader.onload = event => {
                observer.next((<any>event.target).result);
                observer.complete();
              
                // CHANGE DETECTION SHOULD BE FIRED HERE

                // solution 9, 9.1 - not working
                // (reader as any).refresh();
                // (reader as any).refresh;
            };
            reader.readAsText(blob);
        }
    });
}
fzsnzjdm

fzsnzjdm1#

我的经验- FileReader类在安装了一个插件来处理Ionic框架的文件后引用错误。这个解决方案对Ionic和Angular都很有效。
在根应用程序模块中

@NgModule({
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: initReaderOverride,
      deps: [ReaderService],
      multi: true
    }
  ]
})
export class RootModule {}

我使用了一个单例服务来初始化工厂函数内部的覆盖

export function initReaderOverride (readerService: ReaderService): () => void {
  return () => readerService.init();
}

此处为服务代码

@Injectable({
  providedIn: "root"
})
export class ReaderService {
  private get windowRef (): Window & typeof globalThis {
    return this.document.defaultView
  }

  constructor (@Inject(DOCUMENT) private readonly document: Document) { }

  init (): void {
    (<any>this.windowRef).FileReader = RealFileReader
  }
}

class RealFileReader extends (<any>window).FileReader {
  constructor () {
    super()
    const zoneOriginalInstance = (this as any)["__zone_symbol__originalInstance"]
    return zoneOriginalInstance || this
  }
}

这个黑客节省了我的移动的功能和客户的神经。我希望它也能帮助别人!

相关问题