📜 ⬆️ ⬇️

HTML5: Web Workers and AJAX

HTML5 is entering the development environment more and more. Its important advantage is the availability of such technology as web workers, which allows to some extent to ensure, if not multi-threading, then its similarity when executing scripts.

The essence of the technology is simple - functions that support the functioning of AJAX, or functions that process large arrays of information that reduce the speed of page construction during operation, are put into separate files. There may be as many such files as you need. When the script is executed on the browser side, a special Worker object is created, which is responsible for calling the necessary functions. Many modern browsers support this technology.

Now about how to use workers.
Let's check the browser support for the object:
')
if (!!window.Worker) { //  } 

Creating an object is very simple:
 var worker = new Worker(    ); 

The object we created has the following methods:

postMessage (); // key method initializing data exchange
onmessage (); // method executed upon receipt of a response from the called employee.
onerror (); // method called when errors occur

Now let's make the worker file itself and name it worker.js. Inside we place the following code:
 onmessage = function(ev) { var answ = ev.data; }; 

We have an object and a file, now it remains only to call it; this is done like this:
 var worker = new Worker('worker.js'); worker.postMessage('Hello World'); 

The ev variable will contain an object, in the data property, which will be what we pass to the function, in our case the string 'Hello World'. You can transmit anything, including complex objects. Now we will make our worker return something to us. To do this, we add the following to the employee’s code in the last line:
 postMessage(answ); 

And in the main script, we define a method that will be called when a message is received from an employee:
 worker.onmessage = function (event) { alert(event.data); }; 


UPD:
Addition from demark :

You also need to add that HTML5 allows you to create a Web Worker without an external file using

blobBuilder'a:
 var worker = new Worker( window.URL.createObjectURL( new BlobBuilder().append( "onmessage = function(e) { postMessage('hello habrahabr'); }" ).getBlob() ) ); worker.postMessage(); 


That's all! The employee can also return us any data. It is worth remembering a few important points, such as:
1. The employee cannot access the DOM in any way. No function that works with DOM that receives data about its state or modifies it is not available inside the employee. Including alert ().
2. The employee has access to:
2.1 navigator
2.2 location object (read only)
2.3 importScripts () method (for accessing script files in the same domain)
2.4 JavaScript objects like Object, Array, Date, Math, String
2.5 XMLHttpRequest
2.6 methods setTimeout () and setInterval ()

So what's the multi-threading itself? And the fact that the objects of workers can be as many as they want and all of them can work at the same time, while the formation of the page will not be stopped, while waiting for a job to complete, a function.

And now about the important, about what is not in any article about workers: in order to get an adequate response when using the AJAX technology, you must send the SYNCHRONOUS requests using the POST method . The reason is simple: with an asynchronous request, the worker must finish the work without waiting for the server to respond. I have never found a logical explanation for why it is not sent by the GET method. You should not worry that everything will rise, since the worker is running in a separate thread, the main script will continue to work without stopping.

When using technology workers to perform simple actions, the speed gain will be minimal. However, with complex calculations, you can significantly speed up the system.

I will give my implementation of this approach:
one.
object responsible for communication with the server:
 function AJAXprov() { var xmlhttp; var answServ; this.provXmlHttp = function() { var xmlhttp; try { xmlhttp = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { xmlhttp = new ActiveXObject('Microsoft.XMLHTTP'); } catch (E) { xmlhttp = false; } } if (!xmlhttp && typeof XMLHttpRequest!='undefined') { xmlhttp = new XMLHttpRequest(); } return xmlhttp; } // -   false/true (/), // -   (POST/GET) // -    (,     , // -  ,    POST  this.sendAnsServ = function (modeWork, typeSend, adr, param, id, cb) { if(typeSend == 'G') { adr = adr + '?' + param; //alert(adr); httpP.open('GET', adr, modeWork); httpP.setRequestHeader('Cache-Control', 'no-cache, must-revalidate'); httpP.onreadystatechange = function() { if (httpP.readyState == 4) { if(httpP.status == 200) { if(cb) { return httpP.responseText; } } } } httpP.send(null); } if(typeSend == 'P') { httpP.open('POST', adr, modeWork); httpP.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); httpP.setRequestHeader('Cache-Control', 'post-check=0,pre-check=0, false'); httpP.setRequestHeader('Cache-Control', 'max-age=0, false'); httpP.setRequestHeader('Pragma', 'no-cache'); httpP.setRequestHeader('Cache-Control', 'no-cache, must-revalidate'); httpP.send(param); if(httpP.status == 200) { if(cb) { return httpP.responseText; } } } } } 

2
Worker
 onmessage = function (obj) { importScripts("/JS/classes/AjaxClass.js "); var ajObj = new AJAXprov(); httpP = ajObj.provXmlHttp(); obj = obj.data; answ = ajObj.sendAnsServ(objEx.mode, objEx.type, objEx.adress, objEx.parametrs, objEx.ID); postMessage(answ); } 

call:
 function crWorkerAjax(param, id, cb) { var workerAjax = new Worker("/JS/workers/ajaxWorker.js"); var objEx = { mode:false, type:'P', adress:'/router.php', parametrs:param, ID:id, }; workerAjax.onmessage = function (obj) { var res = eval(obj['data']); cb.call(this, res, id); } workerAjax.onerror = function(err) { alert(err.message); } workerAjax.postMessage(objEx); } 


UPD2:
For urgent requests from yui_room9, I cite his alternative version working in webkit browsers

For the main file:
 if (!!window.Worker){ var worker = new Worker('worker.js'); worker.postMessage('Hellow World'); worker.onmessage = function (e){ alert(e.data); }; }  worker: onmessage = function(e){ transport = new XMLHttpRequest(); transport.open('GET', 'data.txt', true); transport.onreadystatechange = function(){ if(transport.readyState == 4){ postMessage(transport.response); } }; transport.send(); }; 


Well, in data.txt we just shove text for a test, I shoved "testing123"

All who read, thank you for your attention.

Source: https://habr.com/ru/post/132785/


All Articles