【问题标题】:Polling from Angular via Core API and Background Service通过核心 API 和后台服务从 Angular 轮询
【发布时间】:2021-06-24 15:49:45
【问题描述】:

我正在尝试通过 BackgroundService 从 Angular 轮询到 .NET Core API。

我将从调用 ApiController 的 Angular 组件传递输入,这将触发 BackgroundService,并且输出会频繁更新回 Angular 组件。

我有几个问题。

  1. 我可以在没有任何外部库的情况下通过这种方式实现轮询吗?
  2. 如何将参数传递给Worker ExecuteAsync
  3. 如何通过GET API调用BackgroundService?

ApiController

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
    private readonly ILogger<TestController> _logger;

    public TestController(ILogger<TestController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public async Task<JsonResult> Get(CancellationToken cancellationToken)
    {
        var output = await Worker   //How to call the worker here and then return the output?
        return new JsonResult(output);
    }
}

工人

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
            
           // Process inputs and return outputs in frequent intervals
        }
    }
}

角度组件

import { Component, Inject } from '@angular/core';
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
})
export class HomeComponent {

  public testForm: FormGroup;
  public test = new  FormControl('1');
  
  constructor(private fb: FormBuilder,
    http: HttpClient, @Inject('BASE_URL') baseUrl: string) {

    const result = interval(2000)
    .pipe(
      switchMap(() => http.get(baseUrl + 'test')),
      map(res => res))

    result.subscribe(res => {
       this.x.setValue(res);
    })
  }
}

【问题讨论】:

    标签: angular asp.net-core-webapi backgroundworker .net-core-angular


    【解决方案1】:

    这里有很多东西,但我认为你只对 Calling worker 感兴趣。

    所以第一步。

    1. 在配置服务中 services.AddScoped();

    2. 在控制器构造函数中。

      私有只读 ILogger _logger; 私有只读 Worker _worker; 公共测试控制器(ILogger 记录器,工人工人) { _logger = 记录器; _worker = 工人; }

       [HttpGet]
       public async Task<JsonResult> Get(CancellationToken cancellationToken)
       {
           var output = await ; //start worker
           return new JsonResult(output);
       }
      

    有两种启动worker的方法。 如果您从后台服务继承,则调用 StartAsync。 如果您已经实现了 IHostedService,那么您必须自己实现。 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio

    注意:我怀疑这种方法不会为您提供更新,因为您正在等待请求完成并且在该结果不会返回之前。

    更新

    对于长时间运行的后台操作,上述方法将不起作用。为此,您必须做更多的工作。

    1. Angular 调用 API 时。
    2. 在某个表或存储中创建一个具有唯一 ID 的工作项。
    3. 将该唯一 ID 返回给 Angular。
    4. 后台服务将根据存储中可用的数据工作,并在存储中保持更新状态。
    5. 基于从 Api 返回到 Angular 的 guid。
    6. 您可以调用另一个 api 函数来检查工作项的状态。

    注意:如果您想避免轮询,则可以根据用例使用 SignalR 或 websocket。

    【讨论】:

    • 谢谢,但这不会以投票方式进行,对吧?它只会返回最终输出
    • 是的。这不是轮询。它将返回最终结果。
    • 谢谢!我正在使用APIWorker 之间的中间件单例类来实现。 Worker 将监视中间件类并对其进行处理。轮询 API 从中间件类返回更新的数据。这是正确的方法吗?
    • 是的。一些您需要将其与主要请求分开的方式。有很多方法,没有好坏之分,这完全取决于您尝试解决的用例和问题。
    • await worker.ExecuteAsync(); 不可用甚至StartAsync ?
    猜你喜欢
    • 1970-01-01
    • 2021-06-28
    • 2012-03-29
    • 1970-01-01
    • 2012-06-05
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 2021-05-02
    相关资源
    最近更新 更多