-
Notifications
You must be signed in to change notification settings - Fork 0
/
poll.ts
64 lines (61 loc) · 1.69 KB
/
poll.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
* @packageDocumentation
* @module @tomato-js/function
*/
type pollOptions<fnValueType> = {
fn: (...args: unknown[]) => fnValueType | PromiseLike<fnValueType>;
validate: (value: fnValueType) => boolean;
interval?: number;
maxAttempts?: number;
};
/**
* 轮询方法,支持同步和异步
*
* 新增于v0.0.16
*
* 脚本举例
* ```
* import { poll } from '@tomato-js/function'
* const { poller, cancel } = poll({
* fn: getUser,
* validate: v => v.result === true,
* interval: 1000,
* maxAttempts: 20
* });
* //手动取消轮询
* setTimeout(() => cancel(), 7000);
* //满足validate后的fn后续回调
* poller.then(data => {
* console.log('poller done')
* console.log(data);
* });
* ```
*
* @param fn - 轮询函数
* @param validate - 验证函数,true则返回resolve
* @param interval - 间隔时间,默认1000毫秒
* @param maxAttempts - 最大尝试次数,默认10次
* @returns 轮询对象,提供轮询Promise和cancel取消轮询方法
*/
export function poll<fnValueType>({ fn, validate, interval = 1000, maxAttempts = 10 }: pollOptions<fnValueType>) {
let attempts = 0;
let canceled = false;
const cancel = () => {
canceled = true;
};
const executePoll = async (resolve: (...args: unknown[]) => unknown, reject: (...args: unknown[]) => unknown) => {
if (canceled) {
return;
}
const result = await fn();
attempts++;
if (validate(result)) {
return resolve(result);
} else if (maxAttempts && attempts === maxAttempts) {
return;
} else {
setTimeout(executePoll, interval, resolve, reject);
}
};
return { poller: new Promise(executePoll), cancel };
}