重复函数本身而不根据其完成情况设置setInterval

时间:2019-05-28 08:51:54

标签: javascript node.js promise async-await setinterval

我需要我的程序不断重复自身。我的程序开始从服务器获取代理并将其保存到数据库,然后将这些保存的代理再次发送到另一台服务器。所以我不知道我的程序需要多长时间来完成这项任务。

我想知道如果发生任何问题使得该startJob()函数花费30秒以上的时间,会发生什么情况。

setInterval是否再次调用它或等待函数完成? 在没有setInterval的情况下,让程序重复执行自身的最佳方法是什么? (例如,在完成后再次调用示例的startJob()。)

我想知道是否可以将此函数放入一个大数字的循环中,如:

for ( let i = 0 ; i < 999999999 ; i ++ ) {
    await startJob()
}

这是我的代码:


const startJob = async () => {
  await postProxyToChannel()
  grabProxies()
}

setInterval(function(){
  startJob()
}, (30000))

在我的服务器上,grabProxies()大约需要10秒,而postProxyToChannel()大约需要5秒。

2 个答案:

答案 0 :(得分:1)

是的,无限循环听起来不错,可以将其与计时器进行比较以暂停循环:

   const timer = ms => new Promise(resolve => setTimeout(resolve, ms));

  (async function() {
     while(true) {
        await postProxyToChannel();
        await grabProxies();
        await timer(30000);
     }
  })();

现在,该循环将运行任务,等待30秒,然后再次执行该操作。因此,循环不会每30秒运行一次,但通常需要更长的时间。要对此进行调整,您可以测量任务花费的时间,然后等待其余时间:

  const start = Date.now();

  await postProxyToChannel();
  await grabProxies();

  await timer(30000 - (Date.now() - start));

答案 1 :(得分:1)

无论startJob内部发生什么,setInterval都会每30秒调用一次。这意味着postProxyToChannel将每30秒被调用一次。如果该函数抛出 ,您将收到未处理的Promise拒绝,但间隔将继续。

即使postProxyToChannel花费了45秒,也不会阻止startJob在先前的startJob完成之前再次被调用。

如果您想确保startJob仅在结束后30秒被调用,则可以在await循环中for对其进行调用,然后await做出以下承诺:每30秒解决一次:

(async () => {
  for ( let i = 0 ; i < 999999999 ; i ++ ) {
    await startJob();
    await new Promise(resolve => setTimeout(resolve, 30000));
  }
})()
  .catch((err) => {
    console.log('There was an error', err);
  });

但是仅仅递归调用startJob可能更有意义,例如:

const startJob = async () => {
  try {
    await postProxyToChannel();
  } catch(e) {
    // handle error
  }
  grabProxies();
  setTimeout(startJob, 30000);
};
startJob();