[英]How to cancel .Net Core Web API request using Angular?
我有以下兩個應用程序
我正在使用 Angular 的HttpClient向 API 發出GET請求,如下所示
this.subscription = this.httpClient.get('api/Controller/LongRunningProcess')
.subscribe((response) =>
{
// Handling response
});
API 控制器的LongRunningProcess方法有以下代碼
[HttpGet]
[Route("LongRunningProcess")]
public async Task<IActionResult> LongRunningProcess(CancellationToken cancellationToken)
{
try
{
// Dummy long operation
await Task.Factory.StartNew(() =>
{
for (int i = 0; i < 10; i++)
{
// Option 1 (Not working)
if (cancellationToken.IsCancellationRequested)
break;
// Option 2 (Not working)
cancellationToken.ThrowIfCancellationRequested();
Thread.Sleep(6000);
}
}, cancellationToken);
}
catch (OperationCanceledException e)
{
Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
}
return Ok();
}
現在我想取消這個長時間運行的過程,所以我從客戶端取消訂閱,如下所示
// On cancel button's click
this.subscription.unsubscribe();
上面的代碼將取消請求,我可以在瀏覽器的“網絡”選項卡中看到它被取消,如下所示
但它不會在 API 的LongRunningProcess方法中使IsCancellationRequested為true ,因此操作將繼續進行。
[注意]:即使我使用郵遞員撥打電話,API 方法中的選項 1和選項 2都不起作用。
問題:有什么方法可以取消LongRunningProcess方法的操作?
當角度取消請求時,您可以從 http 上下文中獲取取消令牌
CancellationToken cancellationToken = HttpContext.RequestAborted;
if (cancellationToken.IsCancellationRequested)
{
// The client has aborted the request
}
在這種情況下你不需要休息只使用這樣
[HttpGet]
[Route("LongRunningProcess")]
public async Task<IActionResult> LongRunningProcess(CancellationToken cancellationToken)
{
for (int i = 0; i < 10; i++)
{
cancellationToken.ThrowIfCancellationRequested();
// Dummy long operation
await Task.Factory.StartNew(() => Thread.Sleep(60000));
}
return Ok();
}
你可以在這里閱讀更多
這是因為您的 dummy long 操作不監視 canncellationToken。 我不確定您是否真的打算毫無延遲地並行啟動 10 個一分鍾的任務,這就是您的代碼所做的。
為了進行虛擬長操作,代碼如下
[HttpGet]
[Route("LongRunningProcess")]
public async Task<IActionResult> LongRunningProcess(CancellationToken cancellationToken)
{
// Dummy long operation
await Task.Run(() =>
{
for (var i = 0; i < 60; i++)
{
if (cancel.IsCancellationRequested)
break;
Task.Delay(1000).Wait();
}
});
return Ok();
}
順便說一下, Task.Run
就相當於Task.Factory.StartNew
。
但是,如果您只需要在 Web API 中進行一個虛擬的長期運行操作,那么您也可以簡單地使用支持取消令牌的Task.Delay
。 Task.Delay
在請求被取消的時候會拋出異常,所以在請求取消后需要做一些事情的時候添加異常處理代碼。
[HttpGet]
[Route("LongRunningProcess")]
public async Task<IActionResult> LongRunningProcess(CancellationToken cancellationToken)
{
// Dummy long operation
await Task.Delay(60000, cancel);
return Ok();
}
除非您在 onDestroy() 中取消訂閱,否則當時仍在運行的任何 http observables 都將完成並運行它們的邏輯。 結果是否微不足道取決於您在訂閱處理程序中所做的事情。 如果您嘗試更新不再存在的內容,您可能會收到錯誤消息。
提示:訂閱包含一個封閉的布爾屬性,在高級情況下可能很有用。 對於 HTTP,這將在完成時設置。 在 Angular 中,在某些情況下,在 ngDestroy 中設置 _isDestroyed 屬性可能很有用,您的訂閱處理程序可以檢查該屬性。
提示 2:如果處理多個訂閱,您可以創建一個臨時的 new Subscription() 對象並向其添加(...)任何其他訂閱 - 因此,當您取消訂閱主要訂閱時,它也會取消訂閱所有添加的訂閱。
因此,最佳實踐是使用 takeUntil() 並在組件被銷毀時取消訂閱 http 調用。
import { takeUntil } from 'rxjs/operators';
.....
ngOnDestroy(): void {
this.destroy$.next(); // trigger the unsubscribe
this.destroy$.complete(); // finalize & clean up the subject stream
}
var cancellationToken = new CanellationToken();
cancellationToken.CancelAfter(2000);
using (var response = await _httpClient.GetAsync("emp",
HttpCompletionOption.ResponseHeadersRead, cancellationTokenSource.Token))
{
response.EnsureSuccessStatusCode();
var stream = await response.Content.ReadAsStreamAsync();
var emp = await JsonSerializer.DeserializeAsync<List<empDto>>(stream, _options);
}
此外,我們還可以擁有這個“CancellationToken”類,它只是 Http 客戶端方法,它在一定的時間間隔后終止請求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.