我有一个相对简单的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;
}
});
如何将其插入到一个可观察的流中,以便我可以将之前的响应传送到它中并等待发送下一个响应,直到上传完成?我尝试过以下方法:
.do(payload => { ... } )
这种工作 - 声明按预期触发,文件上传 - 但下游功能不会等到上传完成,所以我无法以任何方式传递结果。它也感觉很hacky,因为文档暗示.do()
更多地用于记录和较小的效用,而不是整个功能的核心任务。
map
和flatMap
尝试将其纳入流我还尝试将请求功能拆分为以下几个函数:
...
.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
。
我做错了什么,我该怎么做?
答案 0 :(得分: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)