在可观察流中运行HTTP请求

问题描述 投票:0回答:1

我有一个相对简单的HTTP PUT请求:

const req = new HttpRequest('PUT', payload.url, payload.file, {
  reportProgress: true,
  headers: new HttpHeaders().set('Content-Type', 'image/jpeg'),
});

return self.http.request(req).subscribe((event: HttpEvent<any>) => {
  switch (event.type) {
    case HttpEventType.Sent:
      console.log('Request sent!');
      break;
    case HttpEventType.ResponseHeader:
      console.log('Response header received!');
      break;
    case HttpEventType.DownloadProgress:
      const kbLoaded = Math.round(event.loaded / 1024);
      console.log(`Download in progress! ${kbLoaded}Kb loaded`);
      break;
    case HttpEventType.UploadProgress:
      const kbUploaded = Math.round(event.loaded / 1024);
      console.log(`Upload in progress! ${kbUploaded}Kb loaded`);
      break;
    case HttpEventType.Response:
      console.log('😺 Done!', event.body);
      return payload;
  }
});

如何将其插入到一个可观察的流中,以便我可以将之前的响应输入到它中并等待发送下一个响应,直到上传完成?我尝试过以下方法:

  1. 将整个东西包裹在.do(payload => { ... } )

这种工作 - 语句按预期触发,文件上传 - 但下游函数不等到上传完成,所以我不能以任何方式传递结果。它也感觉很hacky,因为文档暗示.do()更多的是用于记录和较小的实用程序,而不是整个功能的核心任务。

  1. 使用mapflatMap尝试将其装入流中

我还尝试将请求功能拆分为以下几个函数:

...
.flatMap(payload => {
  const req = new HttpRequest('PUT', payload.url, payload.file, {
    reportProgress: true,
    headers: new HttpHeaders().set('Content-Type', 'image/jpeg'),
  });

  return self.http.request(req).map((event: HttpEvent<any>) => {
    return { ...payload, event };
  });
})
.map(payload => {
  switch (payload.event.type) {
    case HttpEventType.Sent:
      console.log('Request sent!');
      break;
    case HttpEventType.ResponseHeader:
      console.log('Response header received!');
      break;
    case HttpEventType.DownloadProgress:
      const kbLoaded = Math.round(payload.event.loaded / 1024);
      console.log(`Download in progress! ${kbLoaded}Kb loaded`);
      break;
    case HttpEventType.UploadProgress:
      const kbUploaded = Math.round(payload.event.loaded / 1024);
      console.log(`Upload in progress! ${kbUploaded}Kb loaded`);
      break;
    case HttpEventType.Response:
      console.log('😺 Done!', payload.event.body);
      return [];
  }
})

上传工作,但observable最终发送每个HttpEvent的响应,这不是我想要的。我想只在上传完成时发送回复,即HttpEventType.Response

我做错了什么,我该怎么做?

angular typescript rxjs
1个回答
1
投票

如果您选择不从传递给map的函数返回值,它将执行任何其他JavaScript函数将执行的操作并将返回undefined

所以除了HttpEventType.Response之外的所有情况都会看到undefined被发射到可观察的流中。

如果要忽略其他情况的发射值,请使用filter

.map(payload => {
  switch (payload.event.type) {
    case HttpEventType.Sent:
      console.log('Request sent!');
      break;
    case HttpEventType.ResponseHeader:
      console.log('Response header received!');
      break;
    case HttpEventType.DownloadProgress:
      const kbLoaded = Math.round(payload.event.loaded / 1024);
      console.log(`Download in progress! ${kbLoaded}Kb loaded`);
      break;
    case HttpEventType.UploadProgress:
      const kbUploaded = Math.round(payload.event.loaded / 1024);
      console.log(`Upload in progress! ${kbUploaded}Kb loaded`);
      break;
    case HttpEventType.Response:
      console.log('😺 Done!', payload.event.body);
      return [];
  }
})
.filter(value => Boolean(value)) // filter undefined values

但是,如果你总是返回一个结果,而不是依赖于一个隐含的undefined,那就更清楚了:

.map(payload => {
  switch (payload.event.type) {
    case HttpEventType.Sent:
      console.log('Request sent!');
      return payload;
    case HttpEventType.ResponseHeader:
      console.log('Response header received!');
      return payload;
    case HttpEventType.DownloadProgress:
      const kbLoaded = Math.round(payload.event.loaded / 1024);
      console.log(`Download in progress! ${kbLoaded}Kb loaded`);
      return payload;
    case HttpEventType.UploadProgress:
      const kbUploaded = Math.round(payload.event.loaded / 1024);
      console.log(`Upload in progress! ${kbUploaded}Kb loaded`);
      return payload;
    case HttpEventType.Response:
      console.log('😺 Done!', payload.event.body);
      return { ...payload, body: payload.event.body }; // or whatever
  }
})
.filter(payload => payload.event.type === HttpEventType.Response)
© www.soinside.com 2019 - 2024. All rights reserved.