【问题标题】:How to schedule a task in Angular如何在 Angular 中安排任务
【发布时间】:2021-12-05 04:55:10
【问题描述】:

我必须创建一个 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;});
    }
}

【问题讨论】:

  • 使用计时器触发 clearData 并使用本地存储来存储该数据
  • 是的,我也有同样的想法,但请检查是否有更好的解决方案。

标签: javascript angular scheduled-tasks


【解决方案1】:

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

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

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

【讨论】:

  • 是的,在服务器端添加它更有意义。
【解决方案2】:

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

您创建一个实现此接口的类,当您的 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>

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 如果你设置了一个间隔,它不会被清理,即使组件已经被销毁。您需要手动清洁它。
    • 是的,需要清除 ngOndestroy 中的 Interval。
    【解决方案4】:

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

    Ans 1. 组件作用域只有在它存在于 DOM 中才可用,所以是的,一旦它超出作用域或 DOM,它就会被销毁。

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

    【讨论】:

      猜你喜欢
      • 2012-05-02
      • 2013-03-30
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 2018-05-20
      • 1970-01-01
      相关资源
      最近更新 更多