• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..22-Nov-2021-

dist/H03-May-2022-270235

dynamic/H03-May-2022-164140

examples/H22-Nov-2021-

fixed/H03-May-2022-158136

legacy/H03-May-2022-158136

node_modules/@babel/runtime/H22-Nov-2021-6248

test/resources/H22-Nov-2021-

LICENSEH A D22-Nov-20211 KiB2217

README.mdH A D22-Nov-20219.4 KiB232162

package.jsonH A D22-Nov-20212.5 KiB8887

README.md

1# `setInterval`<wbr>`Async`<br>[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT) [![npm version](https://img.shields.io/npm/v/set-interval-async.svg?style=flat-square)](https://badge.fury.io/js/set-interval-async) [![Build Status](https://img.shields.io/travis/ealmansi/set-interval-async.svg?style=flat-square)](https://travis-ci.org/ealmansi/set-interval-async) [![Coverage Status](https://img.shields.io/coveralls/github/ealmansi/set-interval-async.svg?style=flat-square)](https://coveralls.io/github/ealmansi/set-interval-async?branch=master)  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
2
3Modern version of [setInterval](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) for promises and async functions available in Node.js and browsers.
4
5`setIntervalAsync` works both on Node.js and in the browser, providing the same <br>
6familiar interface as `setInterval` for asynchronous functions, while preventing<br>
7multiple executions from overlapping in time.
8
9
10[![NPM](https://nodei.co/npm/set-interval-async.png)](https://nodei.co/npm/set-interval-async/) [![JavaScript Style Guide](https://cdn.rawgit.com/standard/standard/master/badge.svg)](https://github.com/standard/standard)
11
12# Getting Started
13
14## Node.js
15
16You can install `setIntervalAsync` using npm:
17
18```bash
19npm install -E set-interval-async
20```
21
22Or using Yarn:
23
24```bash
25yarn add -E set-interval-async
26```
27
28Now, you can require `setIntervalAsync` in CommonJS:
29
30```javascript
31// Choose one of the following flavors: dynamic, fixed, legacy.
32
33const { setIntervalAsync } = require('set-interval-async/dynamic')
34const { setIntervalAsync } = require('set-interval-async/fixed')
35const { setIntervalAsync } = require('set-interval-async/legacy')
36const { clearIntervalAsync } = require('set-interval-async')
37
38// Or require all at once:
39
40const {
41  dynamic: { setIntervalAsync: setIntervalAsyncD },
42  fixed: { setIntervalAsync: setIntervalAsyncF },
43  legacy: { setIntervalAsync: setIntervalAsyncL },
44  clearIntervalAsync
45} = require('set-interval-async')
46```
47
48Or else, you can use ES6 modules syntax:
49
50```javascript
51// Choose one of the following flavors: dynamic, fixed, legacy.
52
53import { setIntervalAsync } from 'set-interval-async/dynamic'
54import { setIntervalAsync } from 'set-interval-async/fixed'
55import { setIntervalAsync } from 'set-interval-async/legacy'
56import { clearIntervalAsync } from 'set-interval-async'
57
58// Import all at once:
59
60import {
61  dynamic,
62  fixed,
63  legacy,
64  clearIntervalAsync
65} from 'set-interval-async'
66const { setIntervalAsync: setIntervalAsyncD } = dynamic
67const { setIntervalAsync: setIntervalAsyncF } = fixed
68const { setIntervalAsync: setIntervalAsyncL } = legacy
69
70```
71
72## Browser
73
74In the browser, you can add a script tag in your HTML:
75
76```html
77<script src="https://unpkg.com/set-interval-async"></script>
78```
79
80After the script is loaded, a module `SetIntervalAsync` will be defined in the global context.
81Now, you can retrieve the `setIntervalAsync` function in any of its flavors:
82
83```javascript
84// Choose one of the following flavors: dynamic, fixed, legacy.
85
86var setIntervalAsync = SetIntervalAsync.dynamic.setIntervalAsync
87var setIntervalAsync = SetIntervalAsync.fixed.setIntervalAsync
88var setIntervalAsync = SetIntervalAsync.legacy.setIntervalAsync
89
90// Load `clearIntervalAsync` as well.
91
92var clearIntervalAsync = SetIntervalAsync.clearIntervalAsync
93```
94
95# Usage
96
97In the most basic scenario, you can use `setIntervalAsync` the same way you would use vanilla `setInterval`. For example, the following code:
98
99```javascript
100const {
101  setIntervalAsync,
102  clearIntervalAsync
103} = require('set-interval-async/dynamic')
104
105setIntervalAsync(
106  () => console.log('Hello'),
107  1000
108)
109```
110
111will print 'Hello' to the console once every second. However, you can also provide an async function (or a function returning a promise):
112
113```javascript
114const timer = setIntervalAsync(
115  async () => {
116    console.log('Hello')
117    await doSomeWork()
118    console.log('Bye')
119  },
120  1000
121)
122
123// or equivalently
124
125const timer = setIntervalAsync(
126  () => {
127    console.log('Hello')
128    return doSomeWork().then(
129      () => console.log('Bye')
130    )
131  },
132  1000
133)
134```
135
136which has the added nicety that now you can wait until the cycle is fully stopped before moving on by using `clearIntervalId`. This is particularly useful when, at the end of a unit test, you want to make sure that no asynchronous code continues running by the time your test manager moves on to the next one.
137
138```javascript
139it('should test something', async () => {
140  const timer = setIntervalAsync(
141    /* some async function */,
142    /* some interval */
143  )
144  // Do some assertions.
145  await clearIntervalAsync(timer)
146  // At this point, all timers have been cleared, and the last
147  // execution is guaranteed to have finished as well.
148})
149```
150
151Where `setIntervalAsync` really shines is in those situations where the given asynchronous function might take longer to compute than the configured interval and, at the same time, is not safe to execute more than once at a time. Using vanilla `setInterval` will break your code in this scenario, whereas `setIntervalAsync` guarantees that the function will never execute more than once at the same time. For example, consider:
152
153```javascript
154async function processQueue (queue) {
155  if (queue.length === 0) {
156    return
157  }
158  let head = queue[0]
159  await doSomeWork(head)
160  queue.shift() // Removes the first element.
161}
162```
163
164The function above should never get called again before the previous execution is completed. Otherwise, the queue's first element will get processed twice, and the second element will be skipped. However, with `setIntervalAsync`, the following is perfectly safe:
165
166```javascript
167setIntervalAsync(processQueue, 1000, queue)
168```
169
170since `setIntervalAsync` will guarantee that the function is never executed more than once at any given moment. You can choose whether you wish to use the `Dynamic` or `Fixed` flavors, which will either launch every execution as soon as possible or set a fixed delay between the end of one execution and the start of the next one. See [Dynamic and Fixed `setIntervalAsync`](#dynamic-and-fixed-setintervalasync) for more details.
171
172To see a full set of examples and instructions on how to run them, check out our [examples](https://github.com/ealmansi/set-interval-async/tree/master/examples) directory.
173
174# Motivation
175
176If you've ever had to deal with weird, subtle bugs as a consequence of using `setInterval`[1] on asynchronous functions, or had to manually reimplement `setInterval` using `setTimeout`[2] to prevent multiple executions of the same asynchronous function from overlapping, then this library is a drop-in replacement that will solve your issues.
177
178`setInterval` runs a given function repeateadly, once every fixed number of milliseconds. This may cause problems whenever the function takes longer to execute than the given interval, since it will be called again before the first execution has finished. This is often a problem for non-reentrant functions; ie. functions that are not designed to allow multiple executions at the same time.
179
180`setIntervalAsync` is a drop-in replacement of `setInterval` which shares the same API but is safe to use with non-reentrant, asynchronous functions.
181
182[1] https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout<br>
183[2] https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
184
185# Dynamic and Fixed `setIntervalAsync`
186
187`setIntervalAsync` provides two strategies which can be used to prevent a recurring function from executing more than once at any given moment:
188
189- **Dynamic**: If possible, the given function is called once every `interval` milliseconds. If any execution takes longer than the desired interval, the next execution is delayed until the previous one has finished, and called immediately after this condition is reached.<br><br>![Dynamic setIntervalAsync diagram.](https://github.com/ealmansi/set-interval-async/raw/master/assets/dynamic.png)
190
191- **Fixed**: The given function is called repeatedly, guaranteeing a fixed delay of `interval` milliseconds between the end of one execution and the start of the following one.<br><br>![Fixed setIntervalAsync diagram.](https://github.com/ealmansi/set-interval-async/raw/master/assets/fixed.png)
192
193You can choose whichever strategy works best for your application. When in doubt, the `Dynamic` strategy will likely suffice for most use cases, keeping the interval as close as possible to the desired one.
194
195# Documentation
196
197You can browse the full API in our [Documentation](https://emilio.almansi.me/set-interval-async/) page.
198
199# Contributing
200
201In order to contribute to this project, you will need to first clone the repository:
202
203```bash
204git clone https://github.com/ealmansi/set-interval-async.git
205```
206
207Make sure that [Yarn](https://yarnpkg.com/en/) is installed globally on your system,
208install all project dependencies, and build the project:
209
210```bash
211yarn
212yarn build
213```
214
215Now, you can run the tests and make sure that everything is up and running correctly:
216
217```bash
218yarn test
219```
220
221If the previous step succeeds, you're ready to start developing on this project. <br>Pull requests are welcome!
222
223You can verify that your code follows the [JavaScript Standard Style](https://standardjs.com/) with the following command:
224
225```bash
226yarn lint
227```
228
229# License
230
231[MIT](https://raw.githubusercontent.com/ealmansi/set-interval-async/master/LICENSE)
232