{"id":416,"date":"2016-11-08T11:42:49","date_gmt":"2016-11-08T11:42:49","guid":{"rendered":"http:\/\/fluentreports.com\/blog\/?p=416"},"modified":"2016-11-16T16:35:59","modified_gmt":"2016-11-16T16:35:59","slug":"nativescript-workers","status":"publish","type":"post","link":"http:\/\/fluentreports.com\/blog\/?p=416","title":{"rendered":"NativeScript - Workers"},"content":{"rendered":"<p><a href=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/11\/ns-workers.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-417\" src=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/11\/ns-workers.png\" alt=\"ns-workers\" width=\"835\" height=\"407\" srcset=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/11\/ns-workers.png 835w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/11\/ns-workers-300x146.png 300w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/11\/ns-workers-768x374.png 768w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/11\/ns-workers-624x304.png 624w\" sizes=\"auto, (max-width: 835px) 100vw, 835px\" \/><\/a>One of the best new features in the brand new 2.4.0 release of NativeScript is WebWorkers.\u00a0\u00a0\u00a0 For those who have seen me around in the community; you will probably all know how long I have been harassing the NativeScript Core Teams to get this done (Since Aug of 2015).\u00a0 I even went so far as to create a plugin (NativeScript-WebWorkers) that allowed you to spin up more JS threads but with the major limitation that they didn't have access to the native OS side of things, they were only pure JS. \u00a0\u00a0 So getting real 100% NativeScript webworkers this release means I am a VERY happy camper!<\/p>\n<p>The feature is fully cross platform (i.e. works on iOS and Android) and allows you to spin up additional JavaScript engines to do all your heavy lifting needs in the background. \u00a0\u00a0 Now obviously, the more you spin up the more memory and cpu you will use; so you want to treat them as a precious resource and only spin up those you need.\u00a0\u00a0 Let me re-iterate; use these for only heavy duty processes; each worker is another FULL JS engine, which takes a chunk of memory and cpu to just start and maintain.<\/p>\n<p>They still have full access to the iOS and\/or Android runtime just like normal.\u00a0\u00a0 The only difference between them and the main thread is that you do not have any valid access to the GUI or GUI elements.\u00a0\u00a0 You can attempt to modify the GUI, but you will crash your app as you are not allowed in even in a <strong>native<\/strong> app to modify the GUI outside the main thread.\u00a0 Same rules apply to a NativeScript app.<\/p>\n<p>The NativeScript Core Teams modeled the background threads after the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_Workers_API\">web workers model<\/a>.\u00a0 They are created, developed and destroyed the same way as a browser web worker would be.\u00a0\u00a0 So lets dig in.<\/p>\n<p>Everything is passed via messages between the workers and the main thread; so lets look at a sample demo:<\/p>\n<p><code>main file<\/code><br \/>\n<pre>&quot;use strict&quot;;\nexports.onNavigatingTo = function(args) {\n\u00a0\u00a0 let myWorker = new Worker(&#039;.\/myWorker.js&#039;);\n\u00a0&nbsp;&nbsp;myWorker.onmessage = function(msg) {\n\u00a0\u00a0\u00a0\u00a0 console.log(&quot;Hi I&#039;m a message from the worker: &quot;, msg.data);\n&nbsp;&nbsp;&nbsp;&nbsp; myWorker.terminate();&nbsp;&nbsp;\/\/ We no longer need the worker around, so kill it.\n&nbsp;&nbsp; };\n&nbsp;&nbsp; myWorker.onerror = function(err); {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(&quot;Opps, something went wrong in the worker&quot;, err.message);\n&nbsp;&nbsp; };\n&nbsp;&nbsp; setTimeout(function() { worker.postMessage(&quot;a Cool Message&quot;); }, 500);\n}<\/pre><br \/>\n<code>myWorker.js<\/code><br \/>\n<pre>&quot;use strict&quot;;\nrequire(&quot;globals&quot;);\nglobal.onmessage = function(msg) {\n&nbsp;&nbsp;console.log(&quot;Got a message form the main thread!&quot;, msg.data);\n&nbsp;&nbsp;postMessage(&quot;Worker&#039;s cool Message&quot;);\n&nbsp;&nbsp;\/\/ global.close();&nbsp;&nbsp;\/\/ If ran, this would close the worker from inside.\n};\n\nglobal.onerror = function(err) {\n&nbsp;&nbsp;console.log(&quot;We can handle our own errors too&quot;, err.message);\n};\n<\/pre><br \/>\nNow as you can see we have two files; the first file is from the main thread it starts the new worker by doing <code>let myWorker = new Worker([path to worker script]);<\/code> this is how you start a brand new worker.\u00a0\u00a0 The new worker will load that JavaScript file and start it up.\u00a0 Now there are some gotcha's we are going to cover on the worker side that you will want to know about.<\/p>\n<ol>\n<li>You want to <code>require(&#039;globals&#039;);<\/code> as your first or second line. \u00a0\u00a0 If you do NOT require the global module, you will not have access to <code>console<\/code>, <code>setTimeout<\/code> , <code>setInterval<\/code>, and any other function you are used to using globally.\u00a0\u00a0 So requiring this function is pretty important for most workers.<\/li>\n<li>When you assign <code>.onmessage<\/code> (or <code>.onerror<\/code> if you are using it) you must assign them to the global variable.\u00a0 The new version of the Android engine is enforces <code>&quot;use strict&quot;;<\/code> properly and having implied \"this\" variables is NOT allowed.\u00a0 So as a habit when assigning something to the global scope; implicitly use <code>global.<\/code><\/li>\n<li>All messages have a .data parameter that contains the data you sent from the other side.\u00a0 When you do a <code>postMessage({cool: &quot;wow&quot;, I: &quot;am&quot;});<\/code> this will be in <code>msg.data.cool<\/code> and <code>msg.data.I<\/code> in the onmessage message.\u00a0 This might catch you, but is easily fixed.\u00a0 Please make sure that any objects you send across to the other side is fully serializable (i.e. no recursion, no native gui elements) ; if not it will fail unless you use some third party lib to serialize the recursive structure.<\/li>\n<li><code>Terminate()<\/code> or\u00a0<code>Close()<\/code> the webworker if you are no longer going to use it.\u00a0 If you are planning on continuing to use it; then leave it running it is cheaper to leave it running (&amp; not doing anything) than to terminate and restart.<\/li>\n<li>If you get an error message like this: <strong><em>Worker Error: Uncaught TypeError: Cannot read property 'prototype' of undefined<\/em><\/strong> this can mean it can't find the worker file that you wanted to load.\u00a0 Using the tilde to say main app folder '~\/path\/to\/worker' is the easiest way to fix it.\u00a0 <strong>OR<\/strong> it can mean that the file that is required is doing something that is causing the worker to crash.<\/li>\n<li>If you see the error: <strong><code>Uncaught TypeError: global.moduleMerge is not a function <\/code><\/strong>The solution is to do a <strong>require('globals'); <\/strong>at the top of your worker file.<\/li>\n<\/ol>\n<p>Once you understand these items, you are ready to rock and create cool background threads to do all your busy work so that your main thread never freezes again...<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the best new features in the brand new 2.4.0 release of NativeScript is WebWorkers.\u00a0\u00a0\u00a0 For those who have seen me around in the community; you will probably all know how long I have been harassing the NativeScript Core Teams to get this done (Since Aug of 2015).\u00a0 I even went so far as&hellip; <a class=\"more-link\" href=\"http:\/\/fluentreports.com\/blog\/?p=416\">Continue reading <span class=\"screen-reader-text\">NativeScript - Workers<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15,7],"tags":[16,86,85,84],"class_list":["post-416","post","type-post","status-publish","format-standard","hentry","category-nativescript","category-performance","tag-nativescript","tag-threads","tag-web-workers","tag-webworkers","entry"],"_links":{"self":[{"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/416","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=416"}],"version-history":[{"count":6,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/416\/revisions"}],"predecessor-version":[{"id":436,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/416\/revisions\/436"}],"wp:attachment":[{"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=416"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=416"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}