如何将 Fetch API 响应转换为 RxJS Observable?

Posted

技术标签:

【中文标题】如何将 Fetch API 响应转换为 RxJS Observable?【英文标题】:How to convert a Fetch API response to RxJS Observable? 【发布时间】:2017-12-06 05:17:04 【问题描述】:

如何将Fetch API 返回的任何内容转换为RxJS Observable? RxJS.fromPromise 有帮助吗?

【问题讨论】:

如果您正在使用 Angular,您可能需要考虑使用 Angular 的 HTTP 服务;如果不是,您可能需要考虑使用 RxJS 的 AjaxObservable。它们具有可取消的优势;承诺不能取消。 这是一个使用 Observable 的 Angular 应用程序,但这个应用程序在 web worker 中工作。 Angular HTTP 与 web worker 不兼容。我不得不破解它才能工作。它不是仍然使用XMLHttpRequest 与 FetchAPI 相比,它的性能比XMLHttpRequest 更好吗? 【参考方案1】:

看看这个article

var result = Rx.Observable.fromPromise(fetch('http://myserver.com/'));
result.subscribe(x => console.log(x), e => console.error(e));

【讨论】:

【参考方案2】:

由于 fetch 调用返回另一个包含响应对象的 Promise,我将创建自己的 observable:

import  Observable  from 'rxjs';

const data$ = Observable.create(observer => 
  fetch('http://server.com')
    .then(response => response.json()) // or text() or blob() etc.
    .then(data => 
      observer.next(data);
      observer.complete();
    )
    .catch(err => observer.error(err));
);

data$.subscribe(data => /*do something with data*/);

【讨论】:

真的不明白为什么这被否决了。我认为这实际上是一个比公认答案更强大的解决方案。 Observable.fromPromise(fetch(..)) 将立即触发请求,而上述将在.subscribe() 之后有效地启动它。 我看不出有什么理由在这里导入地图运算符。 Observable.create() 已弃用。相反,使用:const data$ = new Observable(observer => ...) @Dacomis 我在文档中看不到任何关于弃用的内容:rxjs-dev.firebaseapp.com/api/index/class/Observable#create @wawka 由于 TSLint,此弃用错误出现在我的 VSCode 中。【参考方案3】:

存在库rxjs-fetch,但我建议不要使用它,而是写:

const getData = (url, params) => 
    return fetch(url, params).then(r => 
        return r.ok ? r.text() : Promise.reject(`$r.statusText $r.status`)
    )


const getDataObserver = (url, params) => Rx.Observable.fromPromise(getData())

(在 NodeJS 中你需要node-fetch)

【讨论】:

【参考方案4】:

我正在使用 rxjs@6。

接受 observables 的操作符(如 flatMapswitchMap 等)也可以接受 promise。 很简单,如下。

somethingObservable.pipe(
    flatMap(() => fetch('http://some.api.com/post/1')),
    subscribe((response) => 
        console.log(response);
    ),
)

【讨论】:

【参考方案5】:

使用 rxjs 6.4,您可以使用 from 运算符

查看此链接:https://www.learnrxjs.io/operators/creation/from.html

示例在 TS 中:

public getModelDetails(): Observable<YourType> 

const apiCall = fetch(`yourURL/modelDetails`)
                   .then(response => response.json())
                   .then(responseJson => 
                          return responseJson as YourType
                    )
return from(apiCall)

【讨论】:

【参考方案6】:

我正在使用 rxjs 6.5.3。我正在使用下面的示例将 Fetch API 响应转换为 RxJS Observable。

const  from  = rxjs;
const  map, switchMap  = rxjs.operators


const observable = from(fetch('data/user.json')).pipe(
    switchMap(response => response.json())
)

observable.subscribe(function(result)
    console.log('result', result);
);

你也可以使用rxjs的fromFetch。但 fetch API 仍处于试验阶段。

【讨论】:

【参考方案7】:

建议使用 observables 取消获取:

function fetch$(url:string, options:RequestInit) 
  return new Observable<Response>(subscriber => 
    const controller = new AbortController();
    options.signal = controller.signal;
    fetch(url, options)
    .then(res => 
      subscriber.next(res);
      subscriber.complete();
    )
    .catch(er => subscriber.error(er));
    return () =>  // <- return the observable teardown function
      controller.abort();
    
  )

见https://davidwalsh.name/cancel-fetch

【讨论】:

以上是关于如何将 Fetch API 响应转换为 RxJS Observable?的主要内容,如果未能解决你的问题,请参考以下文章