2017-10-11 73 views
3

我在ServiceStack API上有一個長時間運行的數據庫複製請求。完成後,它將返回數據庫複製過程的日誌。是否可以通過ServiceStack在長時間運行的請求上傳輸部分結果?

我想響應返回每一行,因爲它被添加到包含數據庫副本日誌的列表對象。

響應將被angular4應用程序接收,所以我猜如果這是可能的,我還需要配置angular4中的某些內容來更改每次響應更新時的狀態(ngrx)。

說實話,我不知道從哪裏開始。

任何人有任何想法?

回答

2

要流在ServiceStack響應你只需要寫入IResponse.OutputStream直接,你可以在你的服務做的事:

public async Task Any(MyRequest request) 
{ 
    foreach (var chunk in Chunks) 
     await base.Response.OutputStream.WriteAsync(chunk, 0, chunk.Length); 
} 

或者通過返回實現IStreamWriterAsyncIStreamWriter,類似這樣的結果:

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); 
    } 
} 

哪些將寫入響應OutputStream的主機不緩衝響應,對於IIS/ASP.NET,您需要確保Response Buffering is disabled。然後

的問題就變成了如何處理這是要手動需要通過處理響應與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堆棧。

如果您只是想在客戶端下載整個響應時通知客戶端更新,我建議您使用類似Server Events的地方,在逐步發送客戶端通知更新的同時將響應傳輸到客戶端。

+0

乾杯 - 看起來像服務器事件很適合我的要求! – Drammy

相關問題