从 xmlHttpRequest 检索结果

retrieve result from xmlHttpRequest

我必须为我的 angular 项目转换本地音频。我找到的唯一方法是通过 XMLHttpRequest :

var xhr = new XMLHttpRequest();       
    xhr.open("GET", "/path/to/local/image/file", true); 
    xhr.responseType = "blob";
    xhr.onload = function (e) {
            console.log(this.response);
            var reader = new FileReader();
            reader.onload = function(event) {
               var res = event.target.result;
               console.log(res)
            }
            var file = this.response;
            reader.readAsDataURL(file)
    };
    xhr.send()

“res”为我的音频提供了 base64。但是我无法检索 res 并将其存储在变量中以在另一个函数中使用它。 我怎样才能做到这一点 ?还有比使用 XMLHttpRequest 更好的方法吗? 提前致谢。

我建议您使用 Angular HTTP 模块。它是 Angular 原生的,因此更容易与应用程序的其他部分集成。

然后您可以使用一个容器(比如 RxJS ReplaySubject 和缓冲区 1)来 cache/hold 来自 HTTP 请求和后续 FileReaderonload 的值回调。

注意:由于这都是异步的,因此任何直接依赖于 HTTP 请求结果的语句都必须在订阅内。有关异步数据如何工作的详细信息,请参阅 here

app.module.ts

import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { HttpClientModule } from "@angular/common/http";

import { AppComponent } from "./app.component";
import { DataService } from './data.service';

@NgModule({
  imports: [BrowserModule, FormsModule, HttpClientModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [DataService]
})
export class AppModule {}

data.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http";    // <-- import `HttpClient`

import { Observable, ReplaySubject } from 'rxjs';

@Injectable()
export class DataService {
  private fileSource: ReplaySubject<any> = new ReplaySubject<any>(1);
  public file$: Observable<any> = this.fileSource.asObservable();

  constructor(private http: HttpClient) {             // <-- inject `HttpClient`
    this.getFile();                                   // <-- trigger file fetch here
  }

  getFile(): void {
    this.http.get('/path/to/local/image/file', { responseType: "blob" }).subscribe({    // <-- add `responseType`
      next: (response: any) => {
        const reader = new FileReader();
        reader.onload = (event) => {                  // <-- arrow function
           this.fileSource.next(event.target.result); // <-- push to the `ReplaySubject`
        }
        reader.readAsDataURL(response)                // <-- should NOT be `this.response`
      },
      error: (error: any) => {
        // handle error
      }
    });
  }
}

app.component.ts

import { Component, OnInit, OnDestroy } from "@angular/core";

import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";

import { DataService } from "./data.service";

@Component({ ... })
export class AppComponent implements OnInit, OnDestroy {
  close$ = new Subject<any>();
  file: any;

  constructor(private _data: DataService) { }

  ngOnInit() {
    this._data.file$.pipe(
      takeUntil(this.close$)
    ).subscribe({
      next: (file: any) => {
        this.file = file;
        // other statements that depend on `this.file`
      }
    });
  }

  ngOnDestroy() {
    this.close$.next();           // <-- close open subscriptions
  }
}

更新

  • responseType 添加到 GET 请求
  • 工作示例:Stackblitz