[JavaScript] Projekt: JavaScript-Thread

Parantatatam

mag Cookies & Kekse
Hallo Tutorianer,

ich bastle seit einiger Zeit an einem kleinen Projekt, welches die Möglichkeit bietet in JavaScript Threads zu erstellen, ohne dass man dafür existierende Dateien verwenden muss (wie es bei WebWorkern normal ist). Dafür setze ich auf WebWorker und BLOBs. Außerdem werden die Threads in Gruppen zusammen gefasst, so dass man diese gesammelt steuern kann.

So erstellt man bei mir einen Thread:
Javascript:
var thread = new Thread(function ( data ) {
  var num = data * 1; // convert to integer
  return ( num * num ); // square of the passed value
});
Das war alles (ja, in diesem Fall sind Threads eher unnötig, aber es reicht als Beispiel). Möchte man jetzt einen Wert an den Thread senden, so geht dies wie folgt:
Javascript:
thread.send( 5, function ( ret ) {
  console.log( ret ); // prints 25
});
Aus meiner Sicht ist dies viel eleganter als alles, was man direkt mit WebWorkern an stellen kann.

Ich würde gerne von euch wissen, was ihr darüber denkt, was man noch verbessern könnte (oder optimieren) und was vielleicht noch nützlich an Funktionen wäre.

Das Projekt findet ihr bei GitHub mit einer Dokumentation und Skripten sowohl unkomprimiert (rein und für require.js) und komprimiert (35 %): https://github.com/MeiKatz/javascript-thread
 
Nein, war es mir bisher nicht. Ich habe, bevor ich mit meinem Projekt angefangen habe, auch nach solchen Projekten gesucht, jedoch immer nur – aus meiner Sicht – sehr unzureichende gefunden. Das von dir verlinkte Projekt, kommt meinen aber sehr nahe, auch wenn es einige Unterschiede gibt. Aber gut zu wissen, dass noch andere so denken wie ich.
 
Zuletzt bearbeitet:
Hi einfach nur crack,

die Idee finde ich sehr interessant!
Ich werde definitiv demnächst mal reinschauen ;)
 
@ComFreek: Mach das mal. Falls meine Erläuterungen bei GitHub nicht ausreichend sollte, könnt ihr natürlich bei mir nachfragen – also besser: ihr sollt.
 
Was nach einem Tag daraus geworden ist?

Ein fast komplettes Rewrite in TypeScript, inkl. QUnit Test Cases :D
https://github.com/ComFreek/ThreadLibrary.js

Die API ist soweit ziemlich ähnlich. Ein Ding habe ich jedoch gravierend geändert:
Javascript:
var funcBody = func.toString().substring(rawFuncCode.indexOf("{") + 1, rawFuncCode.lastIndexOf("}"));
Dies sollte zuverlässiger als deins arbeiten:
Javascript:
var code = callback.toString().match( /^function\s*\([^\)]*\)\s*\{\s*((\S|\s)*\S)\s*\}$/ );
mit welchem ich bei Newlines Probleme bekommen hatte.

Außerdem habe ich Thread und ThreadGroup vollständig unabhängig voneinander erstellt und in 2 Dateien ausgelagert.
 
@ComFreek: Ich finde deine Umsetzung sehr gelungen und werde mich von deiner Umsetzung inspirieren lassen, also was das Erfassen des Codes der Funktion betrifft. Dies war ursprünglich wesentlich nötiger, da ich nicht nur Callback-Funktionen akzeptiert habe, sondern auch HTML-Script-Elemente. Da ich diese aber entfernt habe, dient es momentan nur noch zum Validieren, also um zu ermitteln, ob in der Funktion überhaupt etwas steht.
Das Problem, was du bei dir erzeugst, ist, dass du innerhalb des Threads immer den Variablennamen "data" für die übergebenen Werte nutzen musst.

Außerdem finde ich es eine gute Idee, dass du Thread und ThreadGroup getrennt hast. Da ich bei mir aber erzwinge, dass ein Thread immer zu einer (und zwar genau zu einer) Gruppe gehört, kann ich diese Klassen zwar in unterschiedliche Dateien auslagern, aber ihre Abhängigkeit bleibt dennoch erhalten.

Übrigens habe ich meine Klassen auch noch etwas modifiziert, da ich bemerkt habe, dass es auch Situationen gibt, in denen ein Thread nicht nur einmal am Ende einen Wert ausgibt, sondern auch Situationen, in denen dies kontinuierlich der Fall ist, ohne dass man den Thread jedes Mal von außen starten will. Daher gibt es bei mir jetzt auch eine Methode "send", die man innerhalb eines Threads ausführen kann, um Daten zu übertragen. Und da dadurch auch nicht terminierende Threads entstehen können, gibt es passend dazu eine Methode "stop", welche man sowohl auf einen Thread als auch auf eine ThreadGroup ausführen kann und somit diese Threads in einen Wartezustand versetzt. Vorher ging das bloß mit "kill", aber damit beendet man den Thread komplett.

PS: Wo kann man den TypeScript überhaupt anwenden? Es ist natürlich wesentlich eleganter als nur JavaScript, da man hier auch echte private Variablen hat, aber ich frage mich schon die ganze Zeit, wie es mit der Kompatibilität in den Browsern aussieht.
 
Zuletzt bearbeitet:
Das Problem, was du bei dir erzeugst, ist, dass du innerhalb des Threads immer den Variablennamen "data" für die übergebenen Werte nutzen musst.

Stimmt, muss mal schauen, wie man das lösen könnte.
Ist in der neusten Version gefixt: https://github.com/ComFreek/ThreadLibrary.js?source=cc
Nun wird z.B. folgender Code erzeugt:
Javascript:
this.addEventListener("message", function(evt) {
  var ret = ([rawFuncCode]).call(evt.target, evt.data);
  this.postMessage(ret);
}, false);
Wobei [rawFuncCode] die ganze Funktion inkl. function-Keyword und Parameterliste ist, z.B.:
Javascript:
function test(myData) {}

Deine Änderungen habe ich schon gesehen ;) Es gibt nun sozusagen eine 1 zu 1 Kommunikation zwischen Thread und "Hauptthread".


PS: Wo kann man den TypeScript überhaupt anwenden? Es ist natürlich wesentlich eleganter als nur JavaScript, da man hier auch echte private Variablen hat, aber ich frage mich schon die ganze Zeit, wie es mit der Kompatibilität in den Browsern aussieht.
TypeScript transkompiliert TypeScript zu JavaScript.
Man schreibt TypeScript, bekommt dabei alle Vorteile der zusätzlichen Syntax, etc. und am Ende bekommt man dennoch EcmaScript 3 oder 5 (je nach Option) JavaScript, welches überall unterstütz wird ;)

Installier dir einfach mal TypeScript: http://www.typescriptlang.org/#Download

Dann lade dir einfach mal mein Code herunter und führe build.ps1 oder build.sh aus.

Danach ist im Ordner build/ die Datei all.js vorhanden. Die enthält ganz normales JS.
 
ComFreek hat gesagt.:
Deine Änderungen habe ich schon gesehen ;) Es gibt nun sozusagen eine 1 zu 1 Kommunikation zwischen Thread und "Hauptthread".
Wenn man so möchte, ja. Man kann sich in der entsprechenden README-Datei auch ansehen, wozu dies beispielsweise gut sein könnte.

Außerdem lösche ich in dem Thread-Code noch die Eigenschaften "onmessage", "onerror" und "self", um den direkten Zugriff auf den Worker zu verhindern. Es gab auch die Überlegung, ob ich Eigenschaft "location" mit jener des Skript überschreibe, welches den Thread erstellt hat. Allerdings wurden dabei die Thread-Skripts immer wesentlich größer als das Skript, welches eigentlich ausgeführt werden sollte (also im Vergleich zu meinen Testskripts) Und was ich fast vergessen hatte: die Threads kennen jetzt ihre eigene ID – vielleicht könnte das irgendwann mal nützlich sein.

PS: TypeScript werde ich mir mal anschauen. Es scheint so etwas ähnliches wie Dart und CoffeeScript zu sein.
 
Außerdem lösche ich in dem Thread-Code noch die Eigenschaften "onmessage", "onerror" und "self", um den direkten Zugriff auf den Worker zu verhindern. Es gab auch die Überlegung, ob ich Eigenschaft "location" mit jener des Skript überschreibe, welches den Thread erstellt hat.

Wieso verweigerst du den direkten Zugriff? Ich find's immer schön, wenn man so viel Freiheiten wie möglich auf die native Schnittstelle trotz Framework/Bibliothek hat.
Was soll denn die Eigenschaft "location" besitzen?


PS: Genau, sowas ähnliches.

PSS: Schon 89 Commits :D Respekt.
 
Zurück