[JavaScript] Projekt: JavaScript-Thread

Naja, also das Problem was ich sehe, besteht darin, dass ich damit die Möglichkeit für unerwartetes Verhalten eröffne Und das ist mir eher unlieb. Außerdem würde ich durch eine Änderung von "location" bewirken, dass der Thread beim Zugriff darauf glauben würde, dass er in dem aufrufenden Skript läuft, und nicht in dem BLOB-Objekt, in dem er läuft.

Zu deinem PPS: Ich reiche immer gleich ein, wenn ich etwas gefunden habe, was mir aufgefallen ist, so dass ich es nicht wieder vergesse. Wenn ich mit anderen zusammen arbeiten würde, würde ich da vermutlich anders arbeiten.
 
Ich weiß nicht ob du dich mit Microsoft's Promise-Objekten in der Windows 8 JS-Lib auskennst. Jedenfalls bieten diese Callback-Funktionen für Progress und Finish-Events an ;)

Diese habe ich im Prinzip bei mir jetzt auch drinne:
Javascript:
var thread = new TL.Thread(function (myData) {
  // build and send powers of myData
  for (var i=0; i<5; i++) {
    send(Math.pow(myData, i));
  }
  // send/return last power (=5)
  return Math.pow(myData, i+1);
});

thread.send(5,
  function progress (retVal) {
    log('Got value "' + retVal + '".');
  },
  function finish (retVal) {
    log('Finished with value "' + retVal + '"');
  }
);

Alternativ kann man auch nur eine Funktion an TL.Thread::send() übergeben:
Javascript:
thread.send(5,
  function progressAndFinish (retVal, finished) {
    log('Got value "' + retVal + '".');
    if (finished) {
      log('Finished now');
    }
  }
);
 
Das ist eine hübsche Idee und soweit habe ich noch gar nicht gedacht, da ich die Idee mit dem permanenten Senden und der Möglichkeit einen Thread zu stoppen, erst gestern hatte. Aber das wäre letztendlich die logische Folge, die dazu nicht einmal meinen Ideen widerspricht: top!
 
Ich habe jetzt noch eine Idee verwirklicht: Import von lokalen Funktionen.

Beispiel:
Javascript:
// will be imported into our thread
function square(i) {
	return i*i;
}

var thread = new TL.Thread();

thread.setFunction(function (myData) {
	return square(myData);
}, [square]);

thread.run();

thread.send(5, function (retVal) {
	alert(retVal); // should alert 25
	// Destroy thread (i.e. free memory for BLOB url object)
	this.destroy();
});

Allerdings müssen die Funktionen wirklich mit "function" deklariert werden und dürfen nicht an eine Variable praktisch nur gebunden sein:
Javascript:
function x() {} // works
var x = function y() {} // doesn't work
 
Die Idee mit der destroy-Methode ist durchaus sinnvoll – daran habe ich noch gar nicht gedacht, dass es natürlich auch sinnvoll ist, dass ein Thread erst "gekillt" wird, wenn der Thread ausgeführt wurde. Aber da ich das zufälligerweise schon implementiert habe, passt das auch wieder :) Und die Idee mit dem Importieren der lokalen Funktionen finde ich auch sehr interessant. Ich werde mal schauen, wie ich das bei mir implementieren werde. Die Funktion zum Minimieren von Funktionen habe ich ja bereits in meiner letzten Version (0.3.6) implementiert, so dass ich dies auch auf andere Funktionen implementieren kann.

Nachtrag: Ich habe das Laden der lokalen Funktionen jetzt mal übernommen (also die Idee), und das sieht jetzt bei mir so aus (ich unterscheide nicht zwischen einer Pfadangabe zu einer Datei oder einem Funktionsobjekt):
Javascript:
if ( require.length > 0 ) {
  var local = [],
      files = [],
      key;

  for ( key in require ) {
    if ( typeof require[ key ] === "string" ) {
      files.push( require[ key ] );
    } else if ( typeof require[ key ] === "function" && /^function[ ]+\w+/.test( require[ key ].toString() ) ) {
      local.push( minimize( require[ key ].toString() ) );
    } else {
      throw new ThreadError( "could not load required script or function" );
    }
  }

  if ( local.length > 0 ) {
    code = local.join( ";" ) + ";" + code;
  }

  if ( files.length > 0 ) {
    code = "importScripts(\"" + files.join( "\",\"" ) + "\");" + code;
  }
}
 
Zuletzt bearbeitet:
Die Funktion zum Minimieren von Funktionen habe ich ja bereits in meiner letzten Version (0.3.6) implementiert, so dass ich dies auch auf andere Funktionen implementieren kann.

Stimmt, da wollte ich dich fragen: wozu minimieren? Heutige Browser sind doch sehr optimiert im Hinblick auf JS-Ausführung.

Nachtrag

Array.join statt einer Schleife zu nutzen ist natürlich sehr elegant, da JS zum Glück alle Elemente zuerst in Strings umwandelt. Hab ich gleich mal übernommen ;)

Wobei man externe Dateien auch innerhalb eines Webworkers standardmäßig laden kann, sprich dein's ist nur eine Verinfach der API seitens des Clienten?
 
Ich minimiere es, damit die temporären Skripte eine möglichst geringe Größe aufweisen. Davon erhoffe ich mir, dass es den Cache des Nutzers nicht überlastet. Es kann allerdings auch sein, dass ich mich darüber zu sehr sorge, und das es eigentlich egal ist. Falls letzteres der Fall sein sollte, habe ich immerhin mal eine Funktion in JavaScript geschrieben, die JavaScript-Funktionen minimiert :)
 
Genau, ich habe die API ein bisschen unterteilt: einerseits kann man Skripts, die davor geladen werden sollen, als Option angeben, andererseits kann man mit der Methode import() innerhalb des Threads noch Skripte nachladen. Da ich jetzt aber auch lokale Funktionen davor laden kann, hat diese Möglichkeit noch eine zweite Legitimation bekommen. Ich vermute, dass die Methode import() kaum verwendet werden wird, daher ist sie nur zur Sicherheit da, falls doch einmal jemand ..
 
[...] habe ich immerhin mal eine Funktion in JavaScript geschrieben, die JavaScript-Funktionen minimiert :)
Grund genug :D Der TypeScript-Compiler ist übrigens vollständig selbst in TypeScript/JavaScript geschrieben (deswegen auch so langsam -.-).

Mittlerweile kann ich auch an Variablen gebundene und anonyme Fkt. importieren:
Javascript:
// will be imported into our thread
function square(i) {
	return i*i;
}

// "variable bound" function
var square2 = function (i) {
	return i*i;
}

var thread = new TL.Thread();

thread.setFunction(function (myData) {
	return square(myData) / square2(myData);
	// this should always return 1!
}, [square, {name: "square2", func: square2}] );

Findest du dieses hier (rein stilistisch)
Javascript:
[square, {name: "square2", func: square2}]
oder dieses hier besser?
Javascript:
{"square": square, "square2": square2}

Dies macht es übrigens auch möglich, Funktionen sozusagen umzubenennen innerhalb des Threads:
Javascript:
[{name: "square123", func: square}]
 
Ich persönlich finde die zweite Variante schöner, weshalb ich auch selber gerade dabei bin, dafür eine Lösung zu finden. Allerdings wird das Skript dadurch immer komplexer. Nun gut, solange ich da noch durchsehe, sollte das aber auch machbar sein :) Ansonsten ist mir auch schon aufgefallen, dass die Möglichkeit einer Umbenennung durchaus reizvoll ist. Abgesehen davon, ist die zweite Variante um einiges kürzer und daher für die Entwicklung durchaus praktischer.
Javascript:
var thr = new Thread([ "foo.js", "bar.js", square, { "square2": square2 }], ... );
 
Zurück