added http req cancellation

This commit is contained in:
RandomityGuy 2023-02-13 19:01:15 +05:30
parent 53eda514ba
commit f6231facc2
3 changed files with 32 additions and 5 deletions

View file

@ -7,6 +7,8 @@ typedef HttpRequest = {
var url:String;
var callback:haxe.io.Bytes->Void;
var errCallback:String->Void;
var cancelled:Bool;
var fulfilled:Bool;
};
class Http {
@ -14,6 +16,7 @@ class Http {
static var threadPool:sys.thread.FixedThreadPool;
static var requests:sys.thread.Deque<HttpRequest> = new sys.thread.Deque<HttpRequest>();
static var responses:sys.thread.Deque<() -> Void> = new sys.thread.Deque<() -> Void>();
static var cancellationMutex:sys.thread.Mutex = new sys.thread.Mutex();
#end
public static function init() {
@ -30,12 +33,20 @@ class Http {
static function threadLoop() {
while (true) {
var req = requests.pop(true);
cancellationMutex.acquire();
if (req.cancelled) {
cancellationMutex.release();
continue;
}
cancellationMutex.release();
var http = new sys.Http(req.url);
http.onError = (e) -> {
responses.add(() -> req.errCallback(e));
req.fulfilled = true;
};
http.onBytes = (b) -> {
responses.add(() -> req.callback(b));
req.fulfilled = true;
};
hl.Gc.blocking(true); // Wtf is this shit
http.request(false);
@ -44,14 +55,17 @@ class Http {
}
#end
public static function get(url:String, callback:haxe.io.Bytes->Void, errCallback:String->Void):Void {
public static function get(url:String, callback:haxe.io.Bytes->Void, errCallback:String->Void) {
var req = {
url: url,
callback: callback,
errCallback: errCallback
errCallback: errCallback,
cancelled: false,
fulfilled: false
};
#if sys
requests.add(req);
return req;
#else
js.Browser.window.fetch(url).then(r -> r.arrayBuffer().then(b -> callback(haxe.io.Bytes.ofData(b))), e -> errCallback(e.toString()));
#end
@ -65,4 +79,12 @@ class Http {
}
#end
}
public static function cancel(req:HttpRequest) {
#if sys
cancellationMutex.acquire();
req.cancelled = true;
cancellationMutex.release();
#end
}
}

View file

@ -88,7 +88,7 @@ class Marbleland {
}
public static function getMissionImage(id:Int, cb:Image->Void) {
Http.get('https://marbleland.vani.ga/api/level/${id}/image?width=258&height=194', (imageBytes) -> {
return Http.get('https://marbleland.vani.ga/api/level/${id}/image?width=258&height=194', (imageBytes) -> {
var res = new Image(new hxd.fs.BytesFileSystem.BytesFileEntry('${id}.png', imageBytes));
cb(res);
}, (e) -> {

View file

@ -1,5 +1,6 @@
package src;
import src.Http.HttpRequest;
import gui.Canvas;
import gui.MessageBoxOkDlg;
import haxe.Json;
@ -19,6 +20,7 @@ import src.Util;
import src.Console;
import src.Marbleland;
import src.MarbleGame;
import src.Http;
class Mission {
public var root:MissionElementSimGroup;
@ -44,7 +46,7 @@ class Mission {
var imgFileEntry:hxd.fs.FileEntry;
static var doingLoadPreviewTimeout = false;
static var _previewRequest:HttpRequest;
public function new() {}
@ -162,7 +164,10 @@ class Mission {
onLoaded(Tile.fromBitmap(img));
return null;
} else {
Marbleland.getMissionImage(this.id, (im) -> {
if (_previewRequest != null && !_previewRequest.fulfilled) {
Http.cancel(_previewRequest); // Cancel the previous request to save dequeing
}
_previewRequest = Marbleland.getMissionImage(this.id, (im) -> {
if (im != null) {
onLoaded(im.toTile());
} else {