在 NodeJS 中安排一个异步函数

Posted

技术标签:

【中文标题】在 NodeJS 中安排一个异步函数【英文标题】:Schedule an async function in NodeJS 【发布时间】:2020-02-17 11:24:48 【问题描述】:

我想安排一个异步函数(async/await ruturn 类型)每两分钟运行一次。

我尝试使用通用 setInterval,节点模块,如 node-schedule 、cron、node-cron、async-poll,但无法实现异步函数调用的轮询。

这是我在代码中尝试过的:

cron.schedule("*/2 * * * *", await this.servicesManager.startPoll() => 
               console.log('running on every two minutes');
); // this is not working breaks after first run
            
const job = schedule.scheduleJob(" */1 * * * *", async function() 
   try 
         return await this.ServicesManager.startPoll(); // this function startPoll is undefined when using this 
        catch (e) 
         console.log(e);
   
   console.log('Run on every minute');
);
                    
const event = schedule.scheduleJob("*/2 * * * *", this.ServicesManager.startPoll()); //using node-schedule , breaks after first time
cron.schedule("*/2 * * * *", await this.ServicesManager.startPoll()); // using cron same result as using node-schedule
return await this.ServicesManager.startPoll(); // without polling works

【问题讨论】:

【参考方案1】:

试试这样的

// version 1
cron.schedule("*/2 * * * *", this.servicesManager.startPoll);

// version 2 => if servicesManager needs its `this` reference
cron.schedule("*/2 * * * *", async () => this.servicesManager.startPoll());

//version 3 ==> using node-schedule
schedule.scheduleJob("*/1 * * * *", async () => this.ServicesManager.startPoll());

我不知道您的servicesManager,您可能必须使用上面的“版本 2”才能使其工作。

调度库需要一个函数来执行,但在上面的示例中它们得到了一个已解析的 Promise。

【讨论】:

这是基于 nodejs 的 rest api 服务器代码的一部分,ServicesManager 是功能调用的包装器,控制器从 ServiceManager 进行调用,版本 1 和 2 不起作用,类似于我正在尝试的方式schedule.scheduleJob("*/1 * * * *", async () => this.ServicesManager.startPoll(); );在这里,ServicesManager 调用 startPoll 调用另一个异步函数,并且 startPoll 本身重新运行异步 答案中没有一个代码行在语法上是正确的。【参考方案2】:

就我而言,我使用的是 async/await 函数,例如:

myService.ts :

    @Cron(CronExpression.EVERY_10_SECONDS)
  async myExample() 
    const todaysDate: dayjs.Dayjs = dayjs();
    Logger.log(`Cron started at $todaysDate`);
    const users = await this.myRepo.getUsers();
   // code here
  

myRepo.ts:

    getUsers() 
    return this.myModel.find();
  

但它不起作用,因此更改了 myService.ts 并尝试了 then

    @Cron(CronExpression.EVERY_10_SECONDS)
  async myExample() 
    const todaysDate: dayjs.Dayjs = dayjs();
    Logger.log(`Cron started at $todaysDate`);
    this.myRepo.getUsers().then(users => 
      // code here
    );
  

【讨论】:

【参考方案3】:

使用node-cron 至少在v3.0.0 之前,计划的异步调用都不起作用,但我们可以使用node-schedule,如下所示。

JS

schedule.scheduleJob("*/1 * * * *", async () => await this.lifeService.addLife(userId, 1));

TS

import nodeSchedule = require("node-schedule");

const job: nodeSchedule.Job = nodeSchedule.scheduleJob('*/10 * * * * *', async () => 
    const life = await this.lifeService.getLives(userId);
    console.log('user's life', life);
);

【讨论】:

以上是关于在 NodeJS 中安排一个异步函数的主要内容,如果未能解决你的问题,请参考以下文章

如何在nodejs中结合同步和异步功能

nodejs异步调用async

nodejs异步回调函数中this问题,求助

何时使用异步 nodejs?

nodejs 异步应该如何处理

Nodejs 等到异步映射函数完成执行