Альтернатива setInterval для повторения интервала только при выполнении функции - PullRequest
0 голосов
/ 13 июля 2020

Мне нужно какое-либо решение или альтернатива для моего веб-приложения Server Sent Event. Я видел людей, использующих setInterval для SSE, и это хорошо, но у меня есть функция, для полного запуска которой требуется некоторое время. Вот ситуация, из-за которой мое веб-приложение работает некорректно.

Возьмем этот пример в качестве причины root. setTimeout будет выполняться только после 1 se c. И setInterval должен запускать эту функцию, а затем ждать 1/10 se c, а затем повторять.

setInterval( () => {
    setTimeout( function () { console.log("ok")}, 1000)
}, 100)

Но всего за 1 сеанс c setInterval запускает эту функцию 10 раз.

ok
ok
ok
ok
ok
ok
....
....

Это настоящий код. Даже если я задам какие-то условия, эта функция все равно будет выполняться 3 раза. И если я установлю время setInterval равным 10 se c, тогда он будет работать нормально.

Есть ли альтернатива в javascript, которую я могу реализовать для событий, отправленных сервером.

setInterval( () => {
        if ( pu[id] > 0 && pu[id]) {
            connection.query(`SELECT * FROM files WHERE pack_id = ${id} ORDER BY uploaded_at DESC LIMIT ${pu[id]}`, (error, results) => {
                if (error) {
                    console.log(error)
                } else {
                    console.log("SEND") // printing 3 times
                    res.status(200).write(`data: ${JSON.stringify(results)}\n\n`)
                }
                pu[id] = 0
            })
        }
    }, 10)

Ответы [ 3 ]

1 голос
/ 14 июля 2020

Если я правильно понимаю, у вас проблемы с временем setInterval, которое короче, чем время, необходимое для решения вашего запроса?

Если да, вы можете рекурсивно вызвать функцию внутри себя с setTimeout, который стабилизирует интервал между разрешениями.

//query takes 1 second to resolve
function mockQuery () {
  return new Promise((resolve, reject)=> {
  setTimeout(()=> resolve(console.log("ok")),1000);
});
}

async function makeQueryCall(){
  await mockQuery()
  //after resolve it is called again 1/10th of a second later
  setTimeout(()=> makeQueryCall(), 100);
}

makeQueryCall(); 

В вашем коде это может быть

async function makeQueryCall() {
  if(pu[id] > 0 && pu[id]) {
      try {
          let results = await connection.query(`SELECT * FROM files WHERE pack_id = ${id} ORDER BY uploaded_at DESC LIMIT ${pu[id]}`); 
          console.log("SEND") // printing 3 times
          res.status(200).write(`data: ${JSON.stringify(results)}\n\n`)     
      } catch (e) {
          console.log(e)
      }
      setTimeout(()=> makeQueryCall(),10)
  }
}

makeQueryCall();

, хотя может потребоваться дополнительная настройка.

0 голосов
/ 14 июля 2020

setInterval и setTimeout - все asyn c, что означает неблокирование вас ниже кода, setTimeout () будет вызываться 10 раз за 1-ю секунду, первый обратный вызов тайм-аута aka function () {console.log ("ok" ) будет вызываться через 1000 мс, затем 1100 мс для 2-го обратного вызова и т. д.

setInterval( () => {
    setTimeout( function () { console.log("ok")}, 1000)
}, 100)
```
0 голосов
/ 14 июля 2020

В вашем примере, где вы использовали setTimeOut внутри setInterval, он работает абсолютно так, как должен. setInterval запускается 10 раз в секунду, т.е. он вызывает setTimeOut 10 раз за 1 сек c. Теперь эти setTimeOut находятся в стеке, и по истечении времени ожидания 1 сек c они выполняются.

Итак, по прошествии 1 секунды вы увидите 10 console.log (). Что он делает выше.

Переходя к вашему собственному вопросу, setTimeOut и setInterval не подходят для этого. Для этого вам нужно использовать Promise.

...