Как вызывать функцию через фиксированный интервал с обеспечением выполнения предыдущей функции

1

У меня есть функция, основанная на Promise, которую я хочу вызывать с фиксированным интервалом, скажем, каждые 60 секунд. Но я также хочу убедиться, что функция вызывается, только если ранее вызванная функция выполнена полностью, и я хочу продолжать это в течение бесконечного времени

function fun(){
    return new Promise((resolve,reject)=>{
        //Some database queries which may or may not complete in 60 seconds
        resolve("done")
    })
}

setInterval(()=>{
    fun().then(d=>{
        console.log(d)
    })
},60000)

Приведенный выше код не будет проверять, завершена ли ранее вызванная функция или нет. но я хочу убедиться, что

  • 3
    Если вы хотите подождать, пока оно не будет завершено, вам следует вместо этого переключиться на setTimeout
  • 0
    Просто используйте setTimeout вместо setInterval и повторите вызов.
Показать ещё 19 комментариев
Теги:
async-await
promise

3 ответа

2
Лучший ответ

class AsyncQueue {
  constructor() {
    this.queue = null;
  }

  push(task) {
    // If we have task in query, append new at the end, if not execute immediately
    // Every task appended to existing queue will be executed immediately after previous one is finished
    return this.queue = this.queue ? this.queue.then(() => task()) : task();
  }
}

const task = (id) => () => new Promise((resolve) => {
  console.log('Task', id, 'started');
  // Random time betwen 500-1300ms
  const time = Math.round(Math.random() * 800 + 500);
  setTimeout(() => {
    console.log("Finished task '" + id + "' after " + time + "ms");
    resolve();
  }, time);
});
const queue = new AsyncQueue();
let id = 0;
// This will push new task to queue every 1s
setInterval(() => {
  console.log("Pushing new task", ++id);
  queue.push(task(id));
}, 1000);

Конечно, мы можем реализовать это без использования класса

let queue;
function push(task) {
  return queue = queue ? queue.then(() => task()) : task();
}
// or
const push = (task) => queue = queue ? queue.then(() => task()) : task();
  • 0
    Хорошее решение :)
  • 0
    @ Ладно, спасибо, я не люблю усложнять вещи
Показать ещё 2 комментария
1

Вместо вызова функции в setInterval вызывайте ее с помощью setTimeout после получения ответа.

function fun(){
    return new Promise((resolve,reject)=>{
        //Some database queries which may or may not complete in 60 seconds
        resolve("done")
    })
}
//Function to call promise function recursively
function functionCaller(fn){
fn()
.then((response)=>{
   console.log(response)
   setTimeout(() => functionCaller(fn), 6000)
})
}

functionCaller(fun)
1

Что ж, если вы хотите подождать, пока оно не закончится, вам следует позвонить снова после того, как обещание будет выполнено. Таким образом, вы бы вместо этого переключились с setInterval на setTimeout.

Для этого вопроса я изменил время ожидания на 1 секунду.

function fun(){
    return new Promise((resolve,reject)=>{
        //Some database queries which may or may not complete in 60 seconds
        resolve("done")
    })
}

function self() {
  setTimeout(()=>{
      fun().then(d=>{
          console.log(d)
      }).then( self ); // call the setTimeout function again
  },1000);
}

self();

Конечно, выбрать лучшее имя, чем self, это было единственное, что я мог придумать в короткие сроки :)

Обновить

Я думаю, что я изначально неправильно понял вопрос, поэтому вам нужно только перезвонить, если он действительно завершился, и не ждать, пока он закончится, а затем начать новый интервал.

В этом случае вы можете вместо этого сделать что-то вроде этого:

function fun(){
  fun.running = true;
  return new Promise((resolve,reject)=>{
      //Some database queries which may or may not complete in 60 seconds
      resolve("done");
  });
}

setInterval(()=>{
  // just make sure the fun isn't running
  if (!fun.running) {
    fun()
      .then(d=> console.log(d) )
      .catch( err => console.log( err ) ) // error handling here to make sure the next block is run
      .then( () => {
        // and handle the reset of the flag here
        fun.running = false;
      } );
  }
},1000);
  • 0
    Это решение не будет работать для меня. Это также добавит время выполнения этой функции, поэтому она не будет вызываться каждые 1000 мс
  • 0
    @KrunalSonparate Извините, мне кажется, я неправильно понял ваш первоначальный вопрос, но я обновил свой ответ, чтобы пометить его с помощью флажка в функции

Ещё вопросы

Сообщество Overcoder
Наверх
Меню