【问题标题】:What is the suitable http content-type for consuming an asynchronous stream of data?什么是适合使用异步数据流的 http 内容类型?
【发布时间】:2019-12-09 15:07:06
【问题描述】:

我是响应式编程的新手。而且我的应用程序使用了 Angular 和 Spring Webflux 的组合。

所以我有一个服务器端点,它产生延迟 1 秒的 Json_values 流。[Spring - webflux]

@CrossOrigin 
@GetMapping(value = "/flux" , produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public Flux<ObjType> returnFlux()
{
    return Flux.just(Obj1, Obj2, Obj3,...)
        .delayElements(Duration.ofSeconds(1));
}

还有我的客户,即。一旦数据块可用,Angular Http 就会记录响应。 [角度] 我的代码是这样的

public getResponse()
{
    var _reqOptionsArgs= { headers: new HttpHeaders().set( 'Content-Type', 'application/json' ) };

    var observable = this.httpClient.get<any>("http://localhost:8080/flux", _reqOptionsArgs);

    observable.subscribe(val => console.log(val),
                         err => console.error(err),
                         () => console.log('Observer got a complete notification'));
}

现在我希望我的方法在通量发出 json 对象后立即在控制台上记录它们。但是当flux发出5个值时,浏览器在等待5秒后抛出异常:

SyntaxError: Unexpected token { in JSON at position 8
    at JSON.parse (<anonymous>)
    at XMLHttpRequest.onLoad (http://localhost:4200/vendor.js:9848:51)
    at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:3397:31)
    at Object.onInvokeTask (http://localhost:4200/vendor.js:71849:33)
    at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:3396:60)
    at Zone.runTask (http://localhost:4200/polyfills.js:3174:47)
    at ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:3471:34)
    at invokeTask (http://localhost:4200/polyfills.js:4609:14)
    at XMLHttpRequest.globalZoneAwareCallback (http://localhost:4200/polyfills.js:4646:21)

但是当我从浏览器触发 localhost:8080/flux 时,它会在发出对象后立即打印响应。

也许我在 Angular 中为 httpClient 中的响应提供了错误的内容类型。 但与此同时,我很好奇浏览器如何响应那块数据。

【问题讨论】:

  • 你可以试试在选项中使用 {responseType: 'text'}
  • @kunalverma 不走运!我也尝试过其他内容类型。我觉得这些内容类型中的大多数,例如字符串、文本、应用程序/json .. 都希望得到整体响应。我正在寻找的是可以允许 http 使用可用响应而不是等待整个响应的配置。
  • 您的内容类型没问题。 HTTP 协议是一种无连接协议。如果您想继续使用 HTTP,我建议使用 websockets 来实现此类功能或轮询。
  • @RahulJaswal 我说的是“responseType”......你从 web api 得到的响应类型......
  • 您正在发出标准的 http 请求(1 个请求,1 个响应,没有数据流),或者您正在连接到 websocket。角度 http 客户端仅用于 http 请求。如果你想建立一个websocket,你需要做一些不同的事情。但似乎你不确定自己在追求什么

标签: angular spring-webflux project-reactor angular-httpclient


【解决方案1】:

当您的 JSON 无效时会发生此错误。尝试调试到达客户端的 JSON 对象的结构。还可以尝试删除 http-headers 并让 angular http-client 自己处理它们

【讨论】:

    【解决方案2】:

    您遇到的特定错误是因为 Streaming JSON (application/stream+json) 和普通的旧 JSON (application/json) 是两种不同的内容类型。 流式 JSON 的不同之处在于它是由另一个值(通常是换行符)分隔的单个 JSON 对象的集合,因此它本身不是有效的 JSON。

    话虽如此,您将很难为此使用HttpClient - 它旨在读取完整响应然后关闭,而您正在向它发送 JSON 流。 (从本质上讲,它是不适合这项工作的工具。)

    您几乎肯定想改用EventSource,类似于:

    var es = new EventSource("http://localhost:8080/flux");
    es.onmessage = function(e) {
        console.log(e.data);
    }
    

    然后您可以拨打JSON.parse()e.data 上的类似电话,然后从那里做您喜欢的事情。

    这里唯一的缺点是EventSource 不允许您在没有 polyfill 的情况下设置 HTTP 标头 - 但看起来这在这里可能不是问题。

    【讨论】:

      猜你喜欢
      • 2011-07-21
      • 2011-04-28
      • 2012-10-24
      • 2011-04-05
      • 1970-01-01
      • 2012-11-30
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多