CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/util/async-wait.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
/*
7
Wait until some function until of obj is truthy
8
(not truthy includes "throw an exception").
9
10
Waits until "until(obj)" evaluates to something truthy
11
in *seconds* -- set to 0 to disable (sort of DANGEROUS, obviously.)
12
Returns until(obj) on success and raises Error('timeout') or
13
Error('closed') on failure (closed if obj emits
14
'closed' event.
15
16
obj is an event emitter, and obj should emit change_event
17
whenever it changes.
18
19
obj should emit 'close' if it prematurely ends.
20
21
The until function may be async.
22
The timeout can be 0 to disable timeout.
23
*/
24
25
import { callback } from "awaiting";
26
27
import { EventEmitter } from "events";
28
29
interface WaitObject extends EventEmitter {
30
get_state: Function;
31
}
32
33
export async function wait({
34
obj,
35
until,
36
timeout,
37
change_event,
38
}: {
39
obj: WaitObject;
40
until: Function;
41
timeout: number;
42
change_event: string;
43
}): Promise<any> {
44
function wait(cb): void {
45
let fail_timer: any = undefined;
46
47
function done(err, ret?): void {
48
obj.removeListener(change_event, f);
49
obj.removeListener("close", f);
50
if (fail_timer !== undefined) {
51
clearTimeout(fail_timer);
52
fail_timer = undefined;
53
}
54
if (cb === undefined) {
55
return;
56
}
57
cb(err, ret);
58
cb = undefined;
59
}
60
61
async function f() {
62
if (obj.get_state() === "closed") {
63
done(`closed - wait-until - ${change_event}`);
64
return;
65
}
66
let x;
67
try {
68
x = await until(obj);
69
} catch (err) {
70
done(err);
71
return;
72
}
73
if (x) {
74
done(undefined, x);
75
}
76
}
77
78
obj.on(change_event, f);
79
obj.on("close", f);
80
81
if (timeout) {
82
const fail = () => {
83
done("timeout");
84
};
85
fail_timer = setTimeout(fail, 1000 * timeout);
86
}
87
88
// It might already be true (even before event fires):
89
f();
90
}
91
92
return await callback(wait);
93
}
94
95