[英]Is it possible to stream partial results through ServiceStack on a long running request?
我的ServiceStack API上有一个长时间运行的数据库复制请求。 完成后,它返回数据库复制过程的日志。
我希望响应返回每行,因为它被添加到包含db复制日志的List对象。
响应将由angular4应用程序接收,所以我想如果这是可能的,我还需要在angular4中配置一些东西以在每次响应更新时改变状态(ngrx)。
说实话,我不知道从哪里开始。
有人有任何想法吗?
要在ServiceStack中流式传输响应,您只需直接写入IResponse.OutputStream
,您可以在服务中执行此操作:
public async Task Any(MyRequest request)
{
foreach (var chunk in Chunks)
await base.Response.OutputStream.WriteAsync(chunk, 0, chunk.Length);
}
或者通过返回实现IStreamWriterAsync
或IStreamWriter
的结果,例如:
public class StreamChunksResponse : IStreamWriterAsync
{
public IEnumerable<byte[]>> Chunks { get; set; }
public async Task WriteToAsync(
Stream responseStream,
CancellationToken token = default(CancellationToken))
{
foreach (var chunk in Chunks)
await responseStream.WriteAsync(chunk, 0, chunk.Length);
}
}
这将写入不响应缓冲响应的主机的Response OutputStream,对于IIS / ASP.NET,您需要确保禁用响应缓冲 。
然后问题变成如何处理客户端上的部分响应,这需要通过处理readyState == 3
响应来手动编码浏览器的XMLHttpRequest
API,例如:
<script>
var xhr = new XMLHttpRequest();
xhr.open('GET', '/stream');
xhr.seenBytes = 0;
xhr.onreadystatechange = function() {
console.log("state change.. state: "+ xhr.readyState);
if(xhr.readyState == 3) {
var newData = xhr.response.substr(xhr.seenBytes);
console.log("newData: <<" +newData+ ">>");
document.body.innerHTML += "New data: <<" +newData+ ">><br />";
xhr.seenBytes = xhr.responseText.length;
console.log("seenBytes: " +xhr.seenBytes);
}
};
xhr.addEventListener("error", function(e) {
console.log("error: " +e);
});
console.log(xhr);
xhr.send();
</script>
这可能很快变得难以处理,特别是如果您尝试流式传输像JSON这样的序列化格式,您需要确保客户端可以构造有效的JSON格式。
如果您只是想在客户端下载整个响应时通知客户端更新,我建议使用诸如服务器事件之类的内容 ,您可以在将响应流式传输到客户端时逐步发送客户端通知更新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.