Skip to content

Commit bbd0ea6

Browse files
committed
fix(call-limit): Limiter rewrite
1 parent a36e7be commit bbd0ea6

File tree

1 file changed

+69
-59
lines changed

1 file changed

+69
-59
lines changed

call-limit.js

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,99 @@
11
"use strict"
22

3-
var defaultMaxRunning = 50
3+
const defaultMaxRunning = 50
44

5-
var limit = module.exports = function (func, maxRunning) {
6-
var running = 0
7-
var queue = []
5+
const limit = module.exports = function (func, maxRunning) {
6+
const state = {running: 0, queue: []}
87
if (!maxRunning) maxRunning = defaultMaxRunning
98
return function limited () {
10-
var self = this
11-
var args = Array.prototype.slice.call(arguments)
12-
if (running >= maxRunning) {
13-
queue.push({self: this, args: args})
14-
return
9+
const args = Array.prototype.slice.call(arguments)
10+
if (state.running >= maxRunning) {
11+
state.queue.push({obj: this, args})
12+
} else {
13+
callFunc(this, args)
14+
}
15+
}
16+
function callNext () {
17+
if (!state.queue.length) return
18+
const next = state.queue.shift()
19+
callFunc(next.obj, next.args)
20+
}
21+
function callFunc (obj, args) {
22+
const cb = typeof args[args.length-1] === 'function' && args.pop()
23+
try {
24+
++state.running
25+
func.apply(obj, args.concat(function () {
26+
--state.running
27+
process.nextTick(callNext)
28+
if (cb) process.nextTick(() => cb.apply(obj, arguments))
29+
}))
30+
} catch (err) {
31+
--state.running
32+
if (cb) process.nextTick(() => cb.call(obj, err))
33+
process.nextTick(callNext)
1534
}
16-
var cb = typeof args[args.length-1] === 'function' && args.pop()
17-
++ running
18-
args.push(function () {
19-
var cbargs = arguments
20-
-- running
21-
cb && process.nextTick(function () {
22-
cb.apply(self, cbargs)
23-
})
24-
if (queue.length) {
25-
var next = queue.shift()
26-
limited.apply(next.self, next.args)
27-
}
28-
})
29-
func.apply(self, args)
3035
}
3136
}
3237

3338
module.exports.method = function (classOrObj, method, maxRunning) {
3439
if (typeof classOrObj === 'function') {
35-
var func = classOrObj.prototype[method]
40+
const func = classOrObj.prototype[method]
3641
classOrObj.prototype[method] = limit(func, maxRunning)
3742
} else {
38-
var func = classOrObj[method]
43+
const func = classOrObj[method]
3944
classOrObj[method] = limit(func, maxRunning)
4045
}
4146
}
4247

4348
module.exports.promise = function (func, maxRunning) {
44-
var running = 0
45-
var queue = []
49+
const state = {running: 0, queue: []}
4650
if (!maxRunning) maxRunning = defaultMaxRunning
47-
return function () {
48-
var self = this
49-
var args = Array.prototype.slice.call(arguments)
50-
return new Promise(function (resolve) {
51-
if (running >= maxRunning) {
52-
queue.push({self: self, args: args, resolve: resolve})
53-
return
54-
} else {
55-
runNext(self, args, resolve)
56-
}
57-
function runNext (self, args, resolve) {
58-
++ running
59-
resolve(
60-
func.apply(self, args)
61-
.then(function (value) {
62-
finish()
63-
return value
64-
}, function (err) {
65-
finish(err)
66-
throw err
67-
}))
68-
}
69-
70-
function finish () {
71-
-- running
72-
if (queue.length) {
73-
var next = queue.shift()
74-
process.nextTick(runNext, next.self, next.args, next.resolve)
75-
}
76-
}
51+
return function limited () {
52+
const args = Array.prototype.slice.call(arguments)
53+
if (state.running >= maxRunning) {
54+
return new Promise(resolve => {
55+
state.queue.push({resolve, obj: this, args})
56+
})
57+
} else {
58+
return callFunc(this, args)
59+
}
60+
}
61+
function callNext () {
62+
if (!state.queue.length) return
63+
const next = state.queue.shift()
64+
next.resolve(callFunc(next.obj, next.args))
65+
}
66+
function callFunc (obj, args) {
67+
return callFinally(() => {
68+
++state.running
69+
return func.apply(obj, args)
70+
}, () => {
71+
--state.running
72+
process.nextTick(callNext)
7773
})
7874
}
75+
function callFinally (action, fin) {
76+
try {
77+
return Promise.resolve(action()).then(value => {
78+
fin()
79+
return value
80+
}, err => {
81+
fin()
82+
return Promise.reject(err)
83+
})
84+
} catch (err) {
85+
fin()
86+
return Promise.reject(err)
87+
}
88+
}
7989
}
8090

8191
module.exports.promise.method = function (classOrObj, method, maxRunning) {
8292
if (typeof classOrObj === 'function') {
83-
var func = classOrObj.prototype[method]
93+
const func = classOrObj.prototype[method]
8494
classOrObj.prototype[method] = limit.promise(func, maxRunning)
8595
} else {
86-
var func = classOrObj[method]
96+
const func = classOrObj[method]
8797
classOrObj[method] = limit.promise(func, maxRunning)
8898
}
8999
}

0 commit comments

Comments
 (0)