1 | <div align="center" style="text-align: center;">
|
2 | <h1 style="border-bottom: none;">async-poll</h1>
|
3 |
|
4 | <p>Advanced polling module with timeout and metrics collection</p>
|
5 | </div>
|
6 |
|
7 | <hr />
|
8 |
|
9 | [![Follow me][follow-me-badge]][follow-me-url]
|
10 |
|
11 | [![Version][version-badge]][version-url]
|
12 | [![Node version][node-version-badge]][node-version-url]
|
13 | [![MIT License][mit-license-badge]][mit-license-url]
|
14 |
|
15 | [![Downloads][downloads-badge]][downloads-url]
|
16 | [![Total downloads][total-downloads-badge]][downloads-url]
|
17 | [![Packagephobia][packagephobia-badge]][packagephobia-url]
|
18 | [![Bundlephobia][bundlephobia-badge]][bundlephobia-url]
|
19 |
|
20 | [![Build Status][travis-badge]][travis-url]
|
21 | [![CircleCI][circleci-badge]][circleci-url]
|
22 | [![Dependency Status][daviddm-badge]][daviddm-url]
|
23 | [![codecov][codecov-badge]][codecov-url]
|
24 | [![Coverage Status][coveralls-badge]][coveralls-url]
|
25 |
|
26 | [![codebeat badge][codebeat-badge]][codebeat-url]
|
27 | [![Codacy Badge][codacy-badge]][codacy-url]
|
28 | [![Code of Conduct][coc-badge]][coc-url]
|
29 |
|
30 | > Writing your own polling function can be difficult and hard to collect metrics about the polling. `asyncPoll` aims to solve those with modern JavaScript and advanced API. By leveraging `async...await`, asynchronous polling function has never been easier and [Performance Timing/ Timeline API][performance-timeline-api-url] is used to collect metrics about each polling in terms of the duration.
|
31 | >
|
32 | > 🛠Please check if `Performance Timing/ Timeline API` is supported on your browser or Node.js environment.
|
33 |
|
34 | ## Table of contents <!-- omit in toc -->
|
35 |
|
36 | - [Pre-requisites](#pre-requisites)
|
37 | - [Install](#install)
|
38 | - [Usage](#usage)
|
39 | - [TypeScript or native ES modules](#typescript-or-native-es-modules)
|
40 | - [Node.js](#nodejs)
|
41 | - [Browser](#browser)
|
42 | - [ES Modules](#es-modules)
|
43 | - [IIFE](#iife)
|
44 | - [Performance Timing/ Timeline API via `PerformanceObserver`](#performance-timing-timeline-api-via-performanceobserver)
|
45 | - [API Reference](#api-reference)
|
46 | - [AsyncPollOptions](#asyncpolloptions)
|
47 | - [asyncPoll\<T\>(fn, conditionFn[, options])](#asyncpolltfn-conditionfn-options)
|
48 | - [License](#license)
|
49 |
|
50 | ## Pre-requisites
|
51 |
|
52 | - [Node.js][nodejs-url] >= 8.9.0
|
53 | - [NPM][npm-url] >= 5.5.1 ([NPM][npm-url] comes with [Node.js][nodejs-url] so there is no need to install separately.)
|
54 |
|
55 | ## Install
|
56 |
|
57 | ```sh
|
58 | # Install via NPM
|
59 | $ npm install --save async-poll
|
60 | ```
|
61 |
|
62 | ## Usage
|
63 |
|
64 | ### TypeScript or native ES modules
|
65 |
|
66 | ```ts
|
67 | interface NewsData {
|
68 | data: {
|
69 | news: object[];
|
70 | status: number;
|
71 | };
|
72 | }
|
73 |
|
74 | import asyncPoll from 'async-poll';
|
75 |
|
76 | /** Fetch news from a mock URL */
|
77 | const fn = async () => fetch('https://example.com/api/news').then(r => r.json());
|
78 | /** Keep polling until the more than 100 `news` are received or `status` returns `complete` */
|
79 | const conditionFn = (d: NewsData) => d.data.news.length > 100 || d.data.status === 'complete';
|
80 | /** Poll every 2 seconds */
|
81 | const interval = 2e3;
|
82 | /** Timeout after 30 seconds and returns end result */
|
83 | const timeout = 30e3;
|
84 |
|
85 | asyncPoll<NewsData>(fn, conditionFn, { interval, timeout })
|
86 | .then(console.log)
|
87 | .catch(console.error);
|
88 | ```
|
89 |
|
90 | ### Node.js
|
91 |
|
92 | ```js
|
93 | const { asyncPoll } = require('async-poll');
|
94 |
|
95 | /** Fetch news from a mock URL */
|
96 | const fn = async () => fetch('https://example.com/api/news').then(r => r.json());
|
97 | /** Keep polling until the more than 100 `news` are received or `status` returns `complete` */
|
98 | const conditionFn = d => d.data.news.length > 100 || d.data.status === 'complete';
|
99 | /** Poll every 2 seconds */
|
100 | const interval = 2e3;
|
101 | /** Timeout after 30 seconds and returns end result */
|
102 | const timeout = 30e3;
|
103 |
|
104 | asyncPoll(fn, conditionFn, { interval, timeout })
|
105 | .then(console.log)
|
106 | .catch(console.error);
|
107 | ```
|
108 |
|
109 | ### Browser
|
110 |
|
111 | #### ES Modules
|
112 |
|
113 | ```html
|
114 | <script type="module">
|
115 | import { asyncPoll } from 'https://unpkg.com/async-poll@latest/dist/browser.js';
|
116 |
|
117 | /** Fetch news from a mock URL */
|
118 | const fn = async () => fetch('https://example.com/api/news').then(r => r.json());
|
119 | /** Keep polling until the more than 100 `news` are received or `status` returns `complete` */
|
120 | const conditionFn = d => d.data.news.length > 100 || d.data.status === 'complete';
|
121 | /** Poll every 2 seconds */
|
122 | const interval = 2e3;
|
123 | /** Timeout after 30 seconds and returns end result */
|
124 | const timeout = 30e3;
|
125 |
|
126 | asyncPoll(fn, conditionFn, { interval, timeout })
|
127 | .then(console.log)
|
128 | .catch(console.error);
|
129 | </script>
|
130 | ```
|
131 |
|
132 | #### IIFE
|
133 |
|
134 | ```html
|
135 | <script src="https://unpkg.com/async-poll@latest/dist/browser.iife.js"></script>
|
136 | <script>
|
137 | const { asyncPoll } = window.AsyncPoll;
|
138 |
|
139 | /** Fetch news from a mock URL */
|
140 | const fn = async () => fetch('https://example.com/api/news').then(r => r.json());
|
141 | /** Keep polling until the more than 100 `news` are received or `status` returns `complete` */
|
142 | const conditionFn = d => d.data.news.length > 100 || d.data.status === 'complete';
|
143 | /** Poll every 2 seconds */
|
144 | const interval = 2e3;
|
145 | /** Timeout after 30 seconds and returns end result */
|
146 | const timeout = 30e3;
|
147 |
|
148 | asyncPoll(fn, conditionFn, { interval, timeout })
|
149 | .then(console.log)
|
150 | .catch(console.error);
|
151 | </script>
|
152 | ```
|
153 |
|
154 | ### Performance Timing/ Timeline API via `PerformanceObserver`
|
155 |
|
156 | Performance timing data can be obtained via the experimental [Performance Tming API][performance-timing-api-url] that has been added as of [Node.js 8.5.0][nodejs-url] or [Performance Timeline API][performance-timeline-api-url] on browsers.
|
157 |
|
158 | ```ts
|
159 | /** For Node.js **only**, no import is required on browser. */
|
160 | import { PerformanceObserver } from 'perf_hooks';
|
161 |
|
162 | async function main() {
|
163 | let measurements: Record<string, unknown> = {};
|
164 | const perfObs = new PerformanceObserver((list) => {
|
165 | for (const n of list.getEntries()) {
|
166 | measurements[n.name] = n.duration;
|
167 | }
|
168 | });
|
169 | perfObs.observe({ entryTypes: ['measure'] });
|
170 | const d = await asyncPoll(fn, conditionFn, { interval, timeout });
|
171 | perObs.disconnect();
|
172 |
|
173 | return {
|
174 | data: d,
|
175 | measurements,
|
176 | };
|
177 | }
|
178 | ```
|
179 |
|
180 | ## API Reference
|
181 |
|
182 | ### AsyncPollOptions
|
183 |
|
184 | ```ts
|
185 | interface AsyncPollOptions {
|
186 | interval: number;
|
187 | timeout: number;
|
188 | }
|
189 | ```
|
190 |
|
191 | ### asyncPoll\<T\>(fn, conditionFn[, options])
|
192 |
|
193 | - `fn` <[Function][function-mdn-url]> Function to execute for each polling happens.
|
194 | - `conditionFn` <[Function][function-mdn-url]> Function to check the condition before a subsequent polling takes place. The function should return a boolean. If `true`, the polling stops and returns with a value in the type of `T`.
|
195 | - `options` <[AsyncPollOptions][asyncpolloptions-url]> Polling options.
|
196 | - `interval` <[number][number-mdn-url]> Polling interval.
|
197 | - `timeout` <[number][number-mdn-url]> Timeout.
|
198 | - returns: <[Promise][promise-mdn-url]<`T`>> Promise which resolves with a value in the type of `T`.
|
199 |
|
200 | ## License
|
201 |
|
202 | [MIT License](https://motss.mit-license.org/) © Rong Sen Ng (motss)
|
203 |
|
204 |
|
205 | [typescript-url]: https://github.com/Microsoft/TypeScript
|
206 | [nodejs-url]: https://nodejs.org
|
207 | [npm-url]: https://www.npmjs.com
|
208 | [node-releases-url]: https://nodejs.org/en/download/releases
|
209 | [performance-timing-api-url]: https://nodejs.org/api/perf_hooks.html
|
210 | [performance-timeline-api-url]: https://developer.mozilla.org/en-US/docs/Web/API/Performance
|
211 | [asyncpolloptions-url]: #asyncpolloptions
|
212 |
|
213 |
|
214 | [array-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
|
215 | [boolean-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean
|
216 | [function-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
|
217 | [map-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
|
218 | [number-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
|
219 | [object-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
|
220 | [promise-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
221 | [regexp-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
|
222 | [set-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
|
223 | [string-mdn-url]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
|
224 |
|
225 |
|
226 | [follow-me-badge]: https://flat.badgen.net/twitter/follow/igarshmyb
|
227 |
|
228 | [version-badge]: https://flat.badgen.net/npm/v/async-poll?icon=npm
|
229 | [node-version-badge]: https://flat.badgen.net/npm/node/async-poll
|
230 | [mit-license-badge]: https://flat.badgen.net/npm/license/async-poll
|
231 |
|
232 | [downloads-badge]: https://flat.badgen.net/npm/dm/async-poll
|
233 | [total-downloads-badge]: https://flat.badgen.net/npm/dt/async-poll?label=total%20downloads
|
234 | [packagephobia-badge]: https://flat.badgen.net/packagephobia/install/async-poll
|
235 | [bundlephobia-badge]: https://flat.badgen.net/bundlephobia/minzip/async-poll
|
236 |
|
237 | [travis-badge]: https://flat.badgen.net/travis/motss/async-poll?icon=travis
|
238 | [circleci-badge]: https://flat.badgen.net/circleci/github/motss/async-poll?icon=circleci
|
239 | [daviddm-badge]: https://flat.badgen.net/david/dep/motss/async-poll
|
240 | [codecov-badge]: https://flat.badgen.net/codecov/c/github/motss/async-poll?label=codecov&icon=codecov
|
241 | [coveralls-badge]: https://flat.badgen.net/coveralls/c/github/motss/async-poll?label=coveralls
|
242 |
|
243 | [codebeat-badge]: https://codebeat.co/badges/56458b75-7d18-4a52-b3eb-b29f5367e244
|
244 | [codacy-badge]: https://api.codacy.com/project/badge/Grade/fdcab22d5b26401486e89d0ed1124171
|
245 | [coc-badge]: https://flat.badgen.net/badge/code%20of/conduct/pink
|
246 |
|
247 |
|
248 | [follow-me-url]: https://twitter.com/igarshmyb?utm_source=github.com&utm_medium=referral&utm_content=motss/async-poll
|
249 |
|
250 | [version-url]: https://www.npmjs.com/package/async-poll
|
251 | [node-version-url]: https://nodejs.org/en/download
|
252 | [mit-license-url]: https://github.com/motss/async-poll/blob/master/LICENSE
|
253 |
|
254 | [downloads-url]: http://www.npmtrends.com/async-poll
|
255 | [packagephobia-url]: https://packagephobia.now.sh/result?p=async-poll
|
256 | [bundlephobia-url]: https://bundlephobia.com/result?p=async-poll
|
257 |
|
258 | [travis-url]: https://travis-ci.org/motss/async-poll
|
259 | [circleci-url]: https://circleci.com/gh/motss/async-poll/tree/master
|
260 | [daviddm-url]: https://david-dm.org/motss/async-poll
|
261 | [codecov-url]: https://codecov.io/gh/motss/async-poll
|
262 | [coveralls-url]: https://coveralls.io/github/motss/async-poll?branch=master
|
263 |
|
264 | [codebeat-url]: https://codebeat.co/projects/github-com-motss-async-poll-master
|
265 | [codacy-url]: https://www.codacy.com/app/motss/async-poll?utm_source=github.com&utm_medium=referral&utm_content=motss/async-poll&utm_campaign=Badge_Grade
|
266 | [coc-url]: https://github.com/motss/async-poll/blob/master/CODE_OF_CONDUCT.md
|