如何将 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?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 RxJS 以时间间隔调用多个依赖 api 调用

试图将 jquery AJAX 转换为 Fetch API,如何设置RequestHeader?

如何使用rxjs map挖掘HttpClient get请求响应?

如何在 JavaScript 中将 Ajax 转换为 Fetch API?

我如何使用 fetch API 并在状态下存储响应?

如何在 fetch api 中处理 HTTP 代码 4xx 响应