У меня есть функция, основанная на 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)
Приведенный выше код не будет проверять, завершена ли ранее вызванная функция или нет. но я хочу убедиться, что
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();
Вместо вызова функции в 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)
Что ж, если вы хотите подождать, пока оно не закончится, вам следует позвонить снова после того, как обещание будет выполнено. Таким образом, вы бы вместо этого переключились с 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);