-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
101 lines (76 loc) · 2.04 KB
/
Copy pathindex.js
File metadata and controls
101 lines (76 loc) · 2.04 KB
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
function create(callback){
const tasks = []
let timer = null
let runningTask = null
function remove(task){
const index = tasks.indexOf(task)
if(index === -1)
return
if(runningTask == task)
clearTimeout(timer)
tasks.splice(index, 1)
const nextTask = getNextTask()
start(nextTask)
}
function add(due, payload){
const task = {
due,
payload
}
tasks.push(task)
// if no timer is attached to a task
if(!runningTask)
return start(task)
// current running task will finish earlier than new task return
if(runningTask.due < task.due)
return task
// replace current timer with new task timer as it will finish first
clearTimeout(timer)
return start(task)
}
function getNextTask(){
// find next task that will finish first
if (!tasks.length) return null
return tasks.reduce((min, task) => {
return task.due < min.due ? task : min
}, tasks[0])
}
function start(task){
// save running task
runningTask = task
// maximum ms value for setTimeout
const TIMEOUT_MAX = 2147483647
let delta = task.due - Date.now()
let timerExceed = false
// if task if further in future than TIMEOUT_MAX
// split the runs up and use TIMEOUT_MAX for the run
if(delta > TIMEOUT_MAX){
delta = TIMEOUT_MAX
timerExceed = true
}
timer = setTimeout((task, timerExceed) => {
// if timer did not exceed TIMEOUT_MAX
// finish it with executing callback and removing task
if(!timerExceed){
// run callback for finished task
callback(task.payload, task)
const index = tasks.indexOf(task)
if (index !== -1) {
// remove finished task
tasks.splice(index, 1)
}
}
// get task that will finish next
const nextTask = getNextTask()
if(nextTask)
return start(nextTask)
runningTask = null
}, delta, task, timerExceed)
return task
}
return {
add,
remove
}
}
exports.create = create