A simple poll function based on async, await, and an infinite loop.
Links:
Features:
- Customizable delay via callback function (e.g. to implement exponential backoff)
- Stop polling programmatically (e.g. stop polling once a certain condition is fulfilled)
Install the poll
package.
npm install poll
Import the poll
function and use it.
import { poll } from 'poll'
function fn() {
console.log('Hello, beautiful!')
}
poll(fn, 1000)
Download the poll
module.
curl -O 'https://cdn.jsdelivr.net/npm/poll@latest/dist/poll.js'
Import the poll
function and use it.
<script type="module">
import { poll } from './poll.js'
function fn() {
console.log('Hello, beautiful!')
}
poll(fn, 1000)
</script>
Basic usage of poll
looks like this:
poll(function () {
console.log('Hello, beautiful!')
}, 1000)
Type: () => any
A function to be called every delay
milliseconds. No parameters are passed to fn
upon calling it.
Type: number | (() => number)
The delay (in milliseconds) to wait before calling the function fn
again. If a function is provided instead of a number, it is evaluated during every polling cycle right before the wait period. If the delay is a negative number, zero will be used instead.
Type: () => boolean | Promise<boolean>
Default: () => false
A function returning a boolean (or a function returning a promise resolving to a boolean) indicating whether to stop the polling process. The shouldStopPolling
callback function is called twice during one polling cycle:
- After the result of the call to
fn
was successfully awaited (right before triggering a new delay period). - After the
delay
has passed (right before callingfn
again).
This guarantees two things:
- A currently active execution of
fn
will be completed. - No new calls to
fn
will be triggered.
None.
The poll
function expects two parameters: A callback function and a delay. After calling poll
with these parameters, the callback function will be called. After it’s done being executed, the poll
function will wait for the specified delay
. After the delay, the process starts from the beginning.
const pollDelayInMinutes = 10
async function getStatusUpdates() {
const pokemonId = Math.floor(Math.random() * 151 + 1)
const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonId}/`)
const pokemon = await response.json()
console.log(pokemon.name)
}
poll(getStatusUpdates, pollDelayInMinutes * 60 * 1000)
Note that poll
will not cause a second call to the callback function if the first call is never finishing. For example, if the endpoint /status
does not respond and the server doesn’t time out the connection, poll
will still be waiting for the callback function to resolve until the dusk of time.
You can pass a callback function to poll
for its third parameter. It’s evaluated before and after calls to the polled function. If it evaluates to a truthy value, the poll
function’s loop will stop and the function returns.
let stopPolling = false
function fn() {
console.log('Hello, beautiful!')
}
setTimeout(() => {
stopPolling = true
}, 1000)
poll(fn, 50, () => stopPolling)
In this example, the shouldStopPolling
callback function evaluates to true
after the setTimeout
function causes stopPolling
to be set to true
after 1000 milliseconds. The next time shouldStopPolling
is evaluated, it will cause poll
to exit normally.
You can also provide an asynchronous function for the shouldStopPolling
callback function.
let stopPolling = false
const shouldStopPolling = () => new Promise((resolve) => {
setTimeout(() => {
resolve(stopPolling)
}, 100)
})
function fn() {
console.log('Hello, beautiful!')
}
setTimeout(() => {
stopPolling = true
}, 1000)
poll(fn, 50, shouldStopPolling)
Beware that this function will be called twice per polling cycle.
By providing a function that returns the delay value instead of the delay value itself, you can customize the behavior of the polling interval. In the following example, the delay doubles with each polling cycle.
const pollDelayInMinutes = 1
let delay = pollDelayInMinutes * 60 * 1000
const startTime = Date.now()
async function getStatusUpdates() {
const pokemonId = Math.floor(Math.random() * 151 + 1)
const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonId}/`)
const pokemon = await response.json()
const seconds = (Date.now() - startTime) / 1000
console.log('Seconds passed:', seconds, pokemon.name)
}
const delayCallback = () => {
const currentDelay = delay
delay *= 2
return currentDelay
}
poll(getStatusUpdates, delayCallback)
This package uses semantic versioning.
-
Make some changes and run the tests and the build script.
npm test npm run build
-
Commit the changes.
-
Verify that you’re authenticated with npm.
npm whomai
If you’re not authenticated, do so using
npm login
. -
Change the package’s version locally.
# See `npm version --help` for more options npm version minor
This changes the version number in the package.json file and adds a new git tag matching the new version.
-
Push your changes and the updated git tags separately.
git push git push --tags
-
Publish the package.
npm publish