Wednesday, July 24, 2013

vkThread - execute any js function in a thread.

vkThread is a javascript plugin, which allows you to execute any function of a your code in a thread.

Standalone function: simply pass it as an argument to the vkthread(), and get the result in a callback function. You don't need to create a separate file for each thread, like you normally do with a regular worker.

Object's method: vkthread accepts context as an optional parameter and executes function in its context. Simply pass the object as a context, that's it.

Function with dependencies: vkthread accepts a list of filenames as an optional argument and imports these files in the thread before the function is calling.

Here is a basic example:


function sum(num1, num2) {
    return num1 + num2;
}

/* execute function foo() in the main thread. */
var foo = sum(2,3);

/* open a new thread and execute function foo() in this thread. */
vkthread.exec(sum, [2,3], function(data){ var foo = data; });



vkThread is based on HTML5 "Worker" technology. It also incorporates JSONfn code to implement key tasks. In spite of technical complexity, plugin is super compact. Development version (plain text with comments) is less than 2k. I don't care to minify it.

For examples and documentation see http://www.eslinstructor.net/vkthread/

15 comments:

  1. hi Vadim,

    i try to create thread with dependency :

    function proto_function(e) {
    var x = $(document.createElement('div'));
    return 2;
    }

    vkthread.run(proto_function,
    [
    ],
    ['../jquery-1.9.0.min.js'])
    .then(function (data) {
    console.log('thread successed. : ' + data);
    });

    and always got error
    "Uncaught Error: Uncaught ReferenceError: window is not defined"
    in worker.js:26

    ReplyDelete
  2. Hi Anonymous,

    The error message says that "window is not defined". It means (literary), that window is not defined :) The reason for this error is the fact, that there is no "window" object in a thread. As jQuery 1.9 use window as it's parent, this library doesn't work in a thread.
    If you want simply try/test this plugin, you can play with "underscore" library, which is environment-neutral

    ReplyDelete
  3. Not exactly a question about vkthread, but is it possible to pass an global array to worker, assign it to worker local array, do the calculations and return this local array with postMessage()?
    How vkthread works with case like this one - can I pass a global function that works with global array?

    ReplyDelete
  4. Yes, it's possible.
    Just keep in mind following: data passed between the page and workers are copied. Objects are serialized and subsequently, de-serialized on the other end. The page and worker do not share the same instance. To improve performance, you can pass data by transferring ownership, which is kind of "pass-by-reference".
    Regarding vkThread: it's very easy to implement the task you described above.

    var myArr = [ 1, 2, 3 ];

    function foo( arr ) {
    ........return arr.reverse();
    }

    vkthread.exec( foo, // function to run in a thread;
    ........[ myArr ], // array of arguments for the function;
    ........function( data ){ // callback function;
    ................console.log( data ); // [ 3, 2, 1 ]
    ........}
    );

    You can take a look at http://www.eslinstructor.net/vkthread/ "Function with Dependencies" section. That example sends two arrays as arguments to worker.

    Please let me know if you have any questions about vkThread plugin.

    regards,

    --Vadim

    ReplyDelete
    Replies
    1. So, technically ... if we have an array with objects:
      function parseArray(); //for example foreach object in objArray do object[i].property += value;

      function blablabla() {
      vkthread.exec(parseArray, args, function(data){
      doSomething;
      });
      }

      are args are required and that function(data) what exactly does? If it uses data from non-returning result parseArray, how I can be sure it changes objArray (in copy manner for now)?

      Please enlighten this more :)

      Delete
    2. 1. args are required, but can be empty array:
      vkthread.exec(foo, [ ], . . . );

      2. "function(data) { }" is callback function, "data" is result, returned from worker. If you develop this function so, that it doesn't process returned data, or if your parseArray() function doesn't return result... well, I have no idea how I can help you in this case, sorry.

      Delete
  5. i wan to run following piece of code :

    function sum(num1, num2) {
    var a = multi(10, 20)
    return num1 + num2 + a;
    }

    function mutlit(num1, num2) {
    return num1 * num2;
    }


    vkthread.exec(sum, //function to run in a thread;
    [2,3], //arguments for the function;
    function(data){ // callback function;
    var foo = data;
    console.log(foo);
    },
    this);

    i get following exception:
    Uncaught TypeError: Converting circular structure to JSON

    ReplyDelete
  6. I see a couple of issues with this code.

    1. Pointer "this" as the 4-th argument vkthread.exec(...) function.
    Probable, you want to pass context, but in this case context you're passing is "window" object. That's why you get "cyclic object value" error.

    2. function "sum(...)" depends on function "multi(...)". Which means multi should be either included in library file and this file provided as "dependency" argument, or "multi()" function can be defined inside "sum(...)" function. For example:

    function sum(num1, num2) {

    ....function multi(n, m) { return n * m; }
    ....var a = multi(10, 20);
    ....return num1 + num2 + a;
    }

    vkthread.exec(sum,
    ....[2,3],
    ....function(data){
    ........var foo = data;
    ........console.log(foo);
    ....});


    Hope this helps.

    --Vadim

    ReplyDelete
  7. Hello Vadimk,

    I am developing an Smart Tv App. I have to read 7 rss feed. Hence, I came across your vkthread concept to implement multithreading. Thank you very much for this plugin.

    However i think if we use ur plugin its throwing an error during runtime. Error says, vkthread not defined. I have made sure that the vkthread.js and worker.js both are in same folder.

    I downloaded the vkthread folder as mention in your website documentation page.

    Then i placed vkthread folder in my app's folder named app. Index.html is in root directory of my app. I want to use vkthread.runAll(). Hence, i added these two in my index.html page.


    script src="//code.jquery.com/jquery-1.9.1.min.js"
    script src="../app/vkthread/vkthread.js"

    however, inspite of doing all the above it shows the error saying vkthread undefined.

    when i tried to debug in my own way, i came across error in ur vkthread.js and worker.js.

    My findings are: in vkthread.js error in line : this.path = 'http'+ err.split('http')[1].split('vkthread.js').slice(0,-1) + 'worker.js';

    it throwed error saying that cannot split() of undefined.

    In worker.js: it showed error saying onmessage not definied.

    Please help me in guiding me how to use ur plugin. It solves lot of my exisiting problem.

    Thank you very much.

    ReplyDelete
    Replies
    1. Hi rakesh,

      First of all: how can I reproduce it? What browser do you use for development/testing?
      Do you have this issue in all 3 major browsers or only in one of them?

      To the issue.
      The problem is clear: to get its own location ( path to the vkthread.js and worker.js files) Vkthread() constructor throws an Error() object, catches it and parses error message, trying to extract path. There is no standard on error message format and structure. Different browsers builds this message differently and it’s quite possible, that error message on your development browser is formatted so, that breaks parser on line #56.
      In this case you have two choices:
      1.
      a) Remove (or comment) all code from constructor Vkthread()
      b) set path manually: vkthread.setPath("path/to/vkthread/") see Documentation/Configuration section

      2.
      In constructor, instead of parsing error message, hardcode this path:
      this.path = “path/to/vkthread”;

      I would appreciate if you provide more details about your work/test environment, so that I’ll be able to improve parsing algorithm.

      Thank you,

      --Vadim

      Delete
    2. Hi Vadimk,

      Well the app i am developing is for samsung smart Tv app. I am using Samsung SDK 4.5 for my developement. I am testing my code on the emulator which is provided by samasung sdk and also i am testing my code on Samsung smart tv.

      Well to come to browser, Samsung Tv has chrome browser. So my code will be running on chrome browser.

      I am not able to attach my code or screen shot here. Please tell me someother way with which i can send u code level details.

      And one more question where should i place this vkthread.setPath("path/to/vkthread/") line? i am really sorry, but i couldnot get any clarity from the documnetion page.

      Delete
    3. I would suggest to set vkthread.setPath() function at the top of your script, as it is, in fact, plugin's configuration. Actually, it can be placed at any line, but it must be above the first call of any vkthread.xxx() function, in your case above of vkthread.runAll() function.

      For example:

      line#10 vkthread.setPath('path/to/vkthread/worker.js');
      . . .
      . . .
      line#20 vkthread.runAll( [ [ . . . ], [ . . . ], [ . . . ] ] );

      As I'm not familiar with the environment you work with, I don't know how to test this plugin in the environment. But it should work in Chrome for sure.

      Hope this helps.


      Delete
  8. Sir,

    I had tried the way u have suggested yestarday. however, result was same vkthread not defined. But, i figured out why it was occuring. Now its throwing new error with regard to code inside worker.js.

    Uncaught reference error: in vkthread/worker.js
    "onmessage is not defined ". is the error i am getting...:( .

    I tried modifying the code by making self.onmessage and this.onmessage. But, still it shows the same error "onmessage is not defined ". i am suspect that this error doesnot depend on my developement and testing environment.

    Please help in fixing this problem Sir. i had mentioned abt this error in one of my earlier questions but u have missed it...!!!

    I am troubling you a lot sir but once i am successfull using this plugin....my app will be completed thats the only reason i am desparate to make this plugin run successfully inside my app code.

    ReplyDelete
    Replies
    1. I have another question. If i write a function to read rss feeds.. can i use your plugin to execute that function..? will it execute?

      Delete
  9. Hi Rakesh.

    As I'm not familiar with Samsung SDK emulator, I can't help you with this particular issue. My suggestion is:

    1. Create a very basic webworker or take it from any tutorial.
    2. Run it in Chrome browser.
    3. Run it on real device.
    4. Run it on emulator.
    If it works, we can continue debug vkthread plugin. Maybe emulator simply doesn't support web worker.

    Regarding rss feeds:
    yes, you can. Web worker supports ajax and there is ajax demo on vkThread home page. However, if the only goal is to get rss and bring it in UI, I wouldn't use web worker / multithreading. Promise library (jQuery, when(), etc.) would be the right choice. It provides a way to integrate multiple ajaxes. Web worker make sense to use only to prevent freezing UI while CPU-extensive task is executing; or implement parallel programming to improve performance. However, if you need not only to get these rss, but also parse them and intensively process data, web worker is a good choice.

    --Vadim

    ReplyDelete