如何在 Angular 中安排任务

How to schedule a task in Angular

我必须在 angular 中创建一个组件,每小时清理一次数据库中的数据(通过服务调用),并在 HTML 中显示上次清理时间。几个问题

  1. 当我们从一个组件路由到另一个组件时,组件会自动销毁并丢失所有数据吗?
  2. 是否可以持久化数据并在将来使用它?
@Component({
  selector: 'demo-app',
  template:`
  <button (click)="clearData()"></button>
  <h2>Last synced time: {{ time }}</h2>
  `
})
export class AppComponent {
 
  public time;
 
  constructor(private demoService: DemoService) { }

  // ----> this should be triggered every hour <----
  clearData() {
    this.demoService.deleteData()
      .subscribe((lastCleanTime) => {this.time = lastCleanTime;});
    }
}

我不喜欢通过客户端来做,给它添加一个按钮是可以的运行,想象一下这些情况:

  • 你有 3 个用户,所以这个任务每小时 运行 大约 3 次,如果更多呢?
  • 您没有用户,所以任务永远不会运行。

我更喜欢从服务器端执行此操作,您可以通过 API 更新时间以获得最新时间,或者您可以添加 WebSocket 使其始终更新。

1 是的,当您从一个组件导航到另一个组件时,组件数据会被删除。如果你想在组件被销毁之前做一些事情,你可以使用组件的 ngOnDestroy Lifecycle 方法。

2 您可以在组件之间导航时使用该服务来存储数据。

好的,与其从用户那里获取触发器,不如每小时运行在内部查询一次数据库会更容易How to schedule a database task?请参阅此link。

答案 1. 组件作用域仅在出现在 DOM 之前可用,所以是的,一旦它超出作用域或 DOM.

就会被销毁

答案 2. 您可以使用模型或状态或局部变量来维护数据。

确实应该定期在服务器端执行数据库清理任务 运行。在我参与的 Java 个项目中,我们用 Tomcat 或使用 ServletContextListener 的 Jetty 完成了类似的任务。其他服务器,例如节点,当然有自己的机制。

您创建一个 class 实现此接口,当您的 servlet 启动或销毁时将调用其方法。 在启动方法中,您创建一个线程,每小时循环清理一次数据库,直到 servlet 被销毁:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class DBCleanupContextListener implements ServletContextListener
{
    private ExecutorService threadPool;
    private DBCleanupTask dbCleanupTask;

    public DBCleanupContextListener()
    {
        threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        dbCleanupTask = new DBCleanupTask();
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0)
    {
        threadPool.execute(dbCleanupTask);

        // submit additional tasks here if needed...
        
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0)
    {
        dbCleanupTask.shutdown();
        threadPool.shutdown();
    }

    class DBCleanupTask implements Runnable
    {
        boolean finished = false;
        
        @Override
        public void run()
        {
            while (!finished)
            {
                
                System.out.println("db cleanup code goes here ....");
                
                try
                {
                    Thread.sleep(60 * 60 * 1000); // sleeps 1 hour = 60min*60sec*1000ms
                }
                catch (InterruptedException e)
                {
                    finished = true;
                }
            }
        }
    
        public void shutdown()
        {
            finished = true;
        }
        
    }
}

我有 运行 此代码与 Tomcat、Jetty 和 Spring Boot。理论上它应该 运行 在任何 JavaEE 服务器上,但你需要研究如何配置 servlet。例如,在 Tomcat 上,需要将其添加到 web.xml,如 here:

所述
<web-app ...>
<listener>
    <listener-class>
            com.example.DBCleanupContextListener 
        </listener-class>
</listener>
</web-app>