Last active
July 23, 2021 04:11
-
-
Save divinity76/20fb4c119f60859b6c8d881f09ff0b25 to your computer and use it in GitHub Desktop.
userland-queue for XMLHttpRequest for dealing with >=1400 concurrent requests (this makes 1400 concurrent requests stable on Chrome. Firefox doesn't have a problem with it)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function XMLHttpRequestWithUserlandQueue() { | |
if (!XMLHttpRequestWithUserlandQueue._master_internal) { | |
XMLHttpRequestWithUserlandQueue._master_internal = { | |
"max_concurrent": 100, // warning, while changing this number at runtime *might work*, i have not carefully coded to make sure that it actually *does* work to change this at runtime. | |
"process_queues": function () { | |
while (this.xhrs_ready_to_fire_queue.length > 0 && this.xhrs_running_queue.running_count() < this.max_concurrent) { | |
let to_fire = this.xhrs_ready_to_fire_queue.pop(); | |
let realXHR = new XMLHttpRequest(); | |
let realXHR_key = this.xhrs_running_queue.add(realXHR); | |
realXHR._XMLHttpRequestWithUserlandQueue_key = realXHR_key; | |
let endcb = function () { | |
for(let index in realXHR){ | |
to_fire[index] = realXHR[index]; | |
} | |
XMLHttpRequestWithUserlandQueue._master_internal.xhrs_running_queue.remove(realXHR_key); | |
XMLHttpRequestWithUserlandQueue._master_internal.process_queues(); | |
}; | |
realXHR.addEventListener("load", endcb); | |
realXHR.addEventListener("error", endcb); | |
for (let index in to_fire._local_internal["function_call_queue"]) { | |
let func_data = to_fire._local_internal["function_call_queue"][index]; | |
// todo: to handle the situation where this stuff throws exception, we should probably re-write it to do | |
// some finally{} stuff to fire all the xhrs even when some of them throws exceptions. | |
// cba looking into it now... | |
// realXHR[func_data.function].apply(func_data.original_this, func_data.arguments); | |
realXHR[func_data.function].apply(realXHR, func_data.arguments); | |
} | |
}; | |
}, | |
"xhrs_ready_to_fire_queue": [], | |
"xhrs_running_queue": { | |
"key_counter": -1, // << will this key counter fail sometime after Number.MAX_SAFE_INTEGER / 9007199254740991 members? yes, in theory. in practice it should never be reached though.. | |
"add": function (xhr) { | |
++this["key_counter"]; | |
this[this["key_counter"]] = xhr; | |
return this["key_counter"]; | |
}, | |
"remove": function (keyToRemove) { | |
delete this[keyToRemove]; | |
}, | |
"running_count": function () { | |
let ret = 0; | |
for (let index in this) { | |
if (["key_counter", "add", "remove", "running_count"].indexOf(index) !== -1) { | |
continue; | |
} | |
++ret; | |
} | |
return ret; | |
} | |
} | |
}; | |
} | |
const createObject = function (o) { | |
// i have no idea what im doing, just following https://stackoverflow.com/a/1919670/1067003 | |
function XMLHttpRequestWithUserlandQueue() { } | |
XMLHttpRequestWithUserlandQueue.prototype = o; | |
return new XMLHttpRequestWithUserlandQueue(); | |
}; | |
let _internal = XMLHttpRequestWithUserlandQueue._internal; | |
let ret = createObject(XMLHttpRequestWithUserlandQueue.prototype); | |
ret._local_internal = { | |
"function_call_queue": [], | |
"fire_status": -1 // -1: not ready to fire. 0: ready to fire, but not fired yet. 1: fired | |
}; | |
ret.open = function (method, url, async, user, password) { | |
if (async === undefined) { | |
async = true; | |
arguments[2] = true; // ..ick | |
} | |
if (!async) { | |
throw new Error("this userland hack doesnt support non-async.."); | |
} | |
ret._local_internal["function_call_queue"].push({ | |
"function": "open", | |
"original_this": this, | |
"arguments": arguments | |
}); | |
}; | |
ret.addEventListener = function () { | |
ret._local_internal["function_call_queue"].push({ | |
"function": "addEventListener", | |
"original_this": this, | |
"arguments": arguments | |
}); | |
}; | |
ret.send = function () { | |
ret._local_internal["function_call_queue"].push({ | |
"function": "send", | |
"original_this": this, | |
"arguments": arguments | |
}); | |
ret._local_internal.fire_status = 0; | |
XMLHttpRequestWithUserlandQueue._master_internal.xhrs_ready_to_fire_queue.push(ret); | |
XMLHttpRequestWithUserlandQueue._master_internal.process_queues(); | |
}; | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment