I'm quite sure with this, but just to have your opinion:
Is it somehow possible to perform operations in the background with Javascript if web workers are not available?
Is there perhaps a way to "misuse" the asynchronous setTimeout() function or some other mechanisms?
My goal is to read things from the localStorage, do a few transformations and send them via Ajax.
Thanks.
You can't run operation in background, but you can split it in small chunks, and run each next part with setTimeout. As result browser will have time to render changes and will be responsive to normal actions, while your long process will be executed as well
function iteration(){
do_some_small_amount_of_work();
if (!not_finished)
scheduler.setTimeout(iteration, 1);
}
There is not really multithreading in Javascript, but you can run code asynchronously using setTimeout(code, 0). This queues the function for execution.
Without using web workers, what you've suggested (using setTimeout) is the only way to do it, and of course it's not really "background" at all at that point. Note that you'll need to keep the processing quite short each time you fire the "background" code, because it's not really background code at all; while your code is running, the page will be fairly unresponsive (the degree to which it's unresponsive will vary by browser, but certainly any JavaScript code on the page will have to wait for your function call to finish).
No, there is no way to do anything in the background in Javascript. It's strictly single threaded.
You can use setTimeout or setInterval to do the work in the foreground, but just a small part of it each time. That way the interface is still reasonably responsive as it handles events between your bursts of work.
Related
I'm learning how to emit events using the NodeJS Event module but I'm struggling on a workflow interrogation.
I'd like to listen for new post created on a specific website using web scraping as it doesn't provide any other way.
For now, all I could find was by using a loop every X minutes and emit it once it notices a difference. But it involves a lot of inconvenience :
How to do it in a loop without blocking the whole script
That involves that you need to wait before continuing in the loop
So, how should you listen to events such as a new post? Is looking for differences at regular intervals a good practice?
The scraping is not blocking the whole script : the loading itself is pretty asynchronous, only the parsing part is synchronous.
If the scraping action is done with a promise, you can run promisses in parallel with promises.all, you could also run scraping with setInterval that way it will be started at regular interval even if some of the scrapings are slow or even failing
If you really want to not block the eventloop at all, you can run a worker for each scraping process.
I used to consider async as equavelent as multithreading. Multi tasks will be done parallel. However, in javascript I wrote this and it seems that dosomething will never happen.
setTimeout(1000, dosomething)
while(true){}
Why?
Node.js is a single threaded asynchronous language. As mentioned in another answer
Javascript is single threaded (with the exception of web workers, but that is irrelavent to this example so we will ignore it). What this means is that setTimeout actually does is schedules some code to be executed some time in the future, after at least some amount of time, but only when the browser has stopped whatever else it was doing on the rendering thread at the time, which could be rendering html, or executing javascript.
In your example the execution of the while loop never stops, control is never returned to the top level, so the scheduled setTimeout function is never executed.
Multithreading is one of many ways to implement asynchronous programming. Reacting to events and yielding to a scheduler is one other way, and happens to be the way that javascript in the browser is implemented.
In your example, the event that gave you control and allowed you to call setTimeout must be allowed to complete so that the javascript engine can monitor the timeout and call your doSomething callback when it expires.
I've been reading a lot about the Event Loop, and I understand the abstraction provided whereby I can make an I/O request (let's use fs.readFile(foo.txt)) and just pass in a callback that will be executed once a particular event indicates completion of the file reading is fired. However, what I do not understand is where the function that is doing the work of actually reading the file is being executed. Javascript is single-threaded, but there are two things happening at once: the execution of my node.js file and of some program/function actually reading data from the hard drive. Where does this second function take place in relation to node?
The Node event loop is truly single threaded. When we start up a program with Node, a single instance of the event loop is created and placed into one thread.
However for some standard library function calls, the node C++ side and libuv decide to do expensive calculations outside of the event loop entirely. So they will not block the main loop or event loop. Instead they make use of something called a thread pool that thread pool is a series of (by default) four threads that can be used for running computationally intensive tasks. There are ONLY FOUR things that use this thread pool - DNS lookup, fs, crypto and zlib. Everything else execute in the main thread.
"Of course, on the backend, there are threads and processes for DB access and process execution. However, these are not explicitly exposed to your code, so you can’t worry about them other than by knowing that I/O interactions e.g. with the database, or with other processes will be asynchronous from the perspective of each request since the results from those threads are returned via the event loop to your code. Compared to the Apache model, there are a lot less threads and thread overhead, since threads aren’t needed for each connection; just when you absolutely positively must have something else running in parallel and even then the management is handled by Node.js." via http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/
Its like using, setTimeout(function(){/*file reading code here*/},1000);. JavaScript can run multiple things side by side like, having three setInterval(function(){/*code to execute*/},1000);. So in a way, JavaScript is multi-threading. And for actually reading from/or writing to the hard drive, in NodeJS, if you use:
var child=require("child_process");
function put_text(file,text){
child.exec("echo "+text+">"+file);
}
function get_text(file){
//JQuery code for getting file contents here (i think)
return JQueryResults;
}
These can also be used for reading and writing to/from the hard drive using NodeJS.
Is it possible, or even practical to create a node program (or sub program/loop) that executes independently of the connected clients.
So in my specific use case, I would like to make a mulitplayer game, where each turn a player preforms actions. And at the end of that turn those actions are computed. Is it possible to perform those computations at a specific time regardless of the client/players connecting?
I assume this involves the use of threads somewhere.
Possibly an easier solution would be to compute the outcome when it is observed, but this could cause difficulties if it has an influence in with other entities. But this problem has been a curiosity of mine for a while.
Well, basically, the easiest solution would probably to run the computation onto a cluster. This is spawning a thread who's running independent task and communicating with messages with the main thread.
If you wish however to run a completely separate process (I probably wouldn't, but it is an option), this can happen too. You then just need a communication protocol between the two process. Usually this would be handled by a messaging or a task queue system. A popular queue solving this issue is RabbitMQ.
If the computations each turn is not to heavy you could solve the issue with a simple setTimeout()
function turnCalculations(){
//do loads of stuff every 30 seconds
}
setTimout(turnCalculations,30000)
//normal node server stuff here
This would do the turn calculations every 30 seconds regardless of users connected, but if the calculations take to long they might block your server.
So, after reading a little about non-blocking code, does...
response.write(thisWillTakeALongTime());
...block the process? If so, do we need to pass the response into pretty much every slow function call we make, and have that function handle the response?
Thanks for helping to clarify!
Yes, it will block the event loop. And passing the response object into the slow function won't help, no matter where you call the slow function you will be blocking the event loop.
As to how to fix it, we will need more information.
What is making your slow function slow? Are you performing large calculations?
Are you doing sync versions of file/database calls?
It depends on what you mean by process. The web server has already finished serving the page at this point you js will execute however the request is synchronous so the javascript will continue to devote its in your function until it returns regardless even if take years. (hopefully by this point the browser will detect your script is taking too long and give you the opportunity to kill it). Even still you suffer the embarrassment of the user having to kill your javascript functionality and them not being able to use the page.
So how do you solve the problem. The time when this gets particular important is when your js is making the problem because at the point a whole host of things of things can go wrong. Imagine that your user is on the other side of the earth. the network latency could make your js painfully slow. when using ajax its preferable to use Asynchronous requests which get around this. I personally recommend using jquery as it makes async ajax calls really easy and the documentation on the side is quite straight forward. The other thing I recommend is making the return output small. It made be better to return json output and build the needed html from that.