This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.7 KiB
116 lines
2.7 KiB
'use strict'; |
|
|
|
module.exports = function (PromiseArgument) { |
|
var Promise; |
|
function throat(size, fn) { |
|
var queue = new Queue(); |
|
function run(fn, self, args) { |
|
if (size) { |
|
size--; |
|
var result = new Promise(function (resolve) { |
|
resolve(fn.apply(self, args)); |
|
}); |
|
result.then(release, release); |
|
return result; |
|
} else { |
|
return new Promise(function (resolve) { |
|
queue.push(new Delayed(resolve, fn, self, args)); |
|
}); |
|
} |
|
} |
|
function release() { |
|
size++; |
|
if (!queue.isEmpty()) { |
|
var next = queue.shift(); |
|
next.resolve(run(next.fn, next.self, next.args)); |
|
} |
|
} |
|
if (typeof size === 'function') { |
|
var temp = fn; |
|
fn = size; |
|
size = temp; |
|
} |
|
if (typeof size !== 'number') { |
|
throw new TypeError( |
|
'Expected throat size to be a number but got ' + typeof size |
|
); |
|
} |
|
if (fn !== undefined && typeof fn !== 'function') { |
|
throw new TypeError( |
|
'Expected throat fn to be a function but got ' + typeof fn |
|
); |
|
} |
|
if (typeof fn === 'function') { |
|
return function () { |
|
var args = []; |
|
for (var i = 0; i < arguments.length; i++) { |
|
args.push(arguments[i]); |
|
} |
|
return run(fn, this, args); |
|
}; |
|
} else { |
|
return function (fn) { |
|
if (typeof fn !== 'function') { |
|
throw new TypeError( |
|
'Expected throat fn to be a function but got ' + typeof fn |
|
); |
|
} |
|
var args = []; |
|
for (var i = 1; i < arguments.length; i++) { |
|
args.push(arguments[i]); |
|
} |
|
return run(fn, this, args); |
|
}; |
|
} |
|
} |
|
if (arguments.length === 1 && typeof PromiseArgument === 'function') { |
|
Promise = PromiseArgument; |
|
return throat; |
|
} else { |
|
Promise = module.exports.Promise; |
|
if (typeof Promise !== 'function') { |
|
throw new Error( |
|
'You must provide a Promise polyfill for this library to work in older environments' |
|
); |
|
} |
|
return throat(arguments[0], arguments[1]); |
|
} |
|
}; |
|
|
|
/* istanbul ignore next */ |
|
if (typeof Promise === 'function') { |
|
module.exports.Promise = Promise; |
|
} |
|
|
|
function Delayed(resolve, fn, self, args) { |
|
this.resolve = resolve; |
|
this.fn = fn; |
|
this.self = self || null; |
|
this.args = args; |
|
} |
|
|
|
function Queue() { |
|
this._s1 = []; |
|
this._s2 = []; |
|
} |
|
|
|
Queue.prototype.push = function (value) { |
|
this._s1.push(value); |
|
}; |
|
|
|
Queue.prototype.shift = function () { |
|
var s2 = this._s2; |
|
if (s2.length === 0) { |
|
var s1 = this._s1; |
|
if (s1.length === 0) { |
|
return; |
|
} |
|
this._s1 = s2; |
|
s2 = this._s2 = s1.reverse(); |
|
} |
|
return s2.pop(); |
|
}; |
|
|
|
Queue.prototype.isEmpty = function () { |
|
return !this._s1.length && !this._s2.length; |
|
};
|
|
|