如何从 xhr 返回 Observable

Vla*_*mir 4 reactive-programming observable rxjs angular

我有这样的功能,它只是上传带有 xhr 请求的图像:

public uploadAvatar(avatarFile, callback) {
    return new Promise((resolve, reject) => {
      let formData: any = new FormData();
      let url = 'avatar';
      let imgArr = "avatar";
      let xhr = new XMLHttpRequest();

      formData.append(imgArr, avatarFile, avatarFile.name);
      xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
          if (xhr.status == 200) {
            resolve(JSON.parse(xhr.response));
            callback('success');
          } else {
            reject(xhr.response);
            callback('error');
          }
        }
      };

      xhr.open("POST", environment.baseUrl + url, true);
      xhr.setRequestHeader('Auth', this._auth.getToken());
      xhr.send(formData);
    });
  }
Run Code Online (Sandbox Code Playgroud)

我怎样才能返回 Observable insted Promise?

mar*_*tin 5

eddyP23 的回答几乎是正确的,但还有两件事。

Observables 和 Promises 之间的一个主要区别是,与 Promises 相比,Observables 可以被取消。这与您使用 XHR 执行 AJAX 调用的情况非常相关。虽然可以使用该abort()函数中止 XMLHttpRequest,但您不能中止挂起的 Promise。

但是使用 Observables 你可以。当您完成或取消订阅 Observable 时,您还可以取消 XHR 对象,因为您知道您对它不感兴趣。

另见:https : //medium.com/@benlesh/promise-cancellation-is-dead-long-live-promise-cancellation-c6601f1f5082

因此,当从使用 Promises 转换为 Observables 时,您的功能应该如下所示:

public uploadAvatar(avatarFile, callback) {
    return Rx.Observable.create(function (observer) {
        ...
        xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                observer.onNext(JSON.parse(xhr.response));
                observer.onCompleted();
            } else {
                observer.onError(xhr.response);
            }
        }

        return () => {
            xhr.abort();
        };
    }
)
Run Code Online (Sandbox Code Playgroud)

请注意,我们正在返回一个在处理 Observable 时使用的函数。有关更多信息,请Observable.create查看http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-create

第二件事是,如果您不关心中止 XHR,您可以使用 Promises。RxJS 5 对待 Promise 的方式与 Observable 相同。请注意,这里Observable.from()将一些ObservableInput详细描述为参数:http : //reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObservableInputDoc.html

对您来说,这意味着您可以uploadAvatar()按原样调用,返回的 Promise 将自动转换为 Observables:

Observable.from(uploadAvatar(...))
    .subscribe(...)
Run Code Online (Sandbox Code Playgroud)