I have a bizarre need here, and I am unsure of it's feasibility. I can only think how I would do it using threads (To create another thread that performs a Quine function along side a thread running the script I want to Quine and execute at the same time (without manually adding alerts everywhere!!!), but javascript doesn't have that functionality, right?
I have some JavaScript which is interpreted by an application with minimal JavaScript debugging capability of it's own. My script is falling over and since it also uses some statements only understood by this application I cannot debug this within Firefox or Internet Explorer because they cannot handle these custom statements. What I am hoping I'll be able to achieve is a program that can mimic another program but also perform it's own functions.
For arguments sake say I have a script called hello.js that outputs "Hello World!" 100 times and when provided to the application it interprets this, however falls over at some point but I can't tell why, where and when because of the limited debug capability.
function main(){
for(var i=0; i<100; i++){
alert('Hello World!\n');
}
}
I then want to have a script that I can pass to the application instead that will pretend to be the script above but will also alert before each statement is executed. I could just do this:
function main(){
alert('main()')
for(var i=0; i<100; i++){
alert("alert('Hello World!\n');");
alert('Hello World!\n');
}
}
However I am sure you can see how for a long program this would be an arduous task. Do instead I want to make a program that can perform like this:
function main(){
var text = loadJSScript("C:\\Script\\Hello.js"); //Loads a text/javascript file line by line into an array
for(var i=0; i<text.length; i++){
var statement = text[i];
alert("Line Number: " + i + " Statement: " + statement); //Output the line number and statement before executing
execute(statement); //A function that executes the statement from the other file (as if a separate thread)
}
}
This really depends on your target audience (browser use).
You can get a very effective form of pseudo-threading by using web workers.
http://ejohn.org/blog/web-workers/
However this is not widely supported. You could use this where available.
You can also get some behaviour similar to threading by using setTimeout to execute the code.
You can see how timers are queued here:
http://ejohn.org/blog/how-javascript-timers-work/
You could also do the Quine calculation server side, and call using AJAX. This does give an asynchronous request.
These last 2 options aren't threading, but the code will not wait for a response before continuing.
To my knowledge, JavaScript is purely mono-threaded.
Moreover, the loadJSScript("C:\\Script\\Hello.js"); statement is fishy, since you mention browsers. JS in browsers (in Web pages, at least) cannot access the filesystem (beside, that's not portable!).
You can perhaps do something like that in Microsoft's JScript (in WSH), though.
Related
I'm trying to evaluate the javascript on a page before I do a query because the html that I'm looking for doesn't exist in the AngleSharp document.
There is a method: document.ExecuteScript(string )
But I don't know how to use it compared to how I've seen other libraries used. For example, some python code looks like this...
wait.until(presence_of_element_located((By.ID, "class-name")))
Which just pauses the code I guess until the entire page is evaluated. Elements can then be searched.
In AngleSharp it looks like I have to run ExecuteScript method to do the same thing. But it just throws an exception (Jint.Runtime.JavaScriptException: 'results is not defined') and it returns an object as a result - which is completely obfuscating, not helpful at all.
What do I do so that my next command:
IHtmlCollection<IElement> cells = document.QuerySelectorAll(s);
actually looks through the entire document and not just the initial HTML?
I think there is more than just one question here. So I'll break it down.
First, let's get some basics here:
AngleSharp is a browser core - its not a browser, and it is not a JS engine.
AngleSharp provides the ability to extend it with, for instance, a JS engine. AngleSharp.Js is such an engine based on Jint, however, its still experimental and complicated scripts will definitely not run.
Before we already get into the event loop and async loading details, I'd recommend to make sure that whatever script you expect to run, really runs.
Now to the specifics:
ExecuteScript is a little helper from AngleSharp.Js that actually runs a piece of JS code that you provide. I guess its not at all what you want.
If you just want to "wait" until something is there you can do that with a few lines of C# code:
var maxTime = TimeSpan.FromSeconds(1.5);
var totalTime = TimeSpan.Zero;
var pollTime = TimeSpan.FromMilliseconds(25);
while (totalTime < maxTime)
{
await Task.Delay(pollTime.Milliseconds);
// check condition
if (document.QuerySelector(".foo.bar") != null)
{
// run zoned code
break;
}
totalTime += pollTime;
}
AngleSharp.Js actually has various methods to get into the event loop, i.e., to wait until JS has completed the current work.
For instance, WaitUntilAvailable() can be used to wait until the load event (and related) has been handled.
To enqueue some action the Then() extension method was added. All these extension methods live directly on the IDocument instance.
I've been using selenium (with python bindings and through protractor mostly) for a rather long time and every time I needed to execute a javascript code, I've used execute_script() method. For example, for scrolling the page (python):
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
Or, for infinite scrolling inside an another element (protractor):
var div = element(by.css('div.table-scroll'));
var lastRow = element(by.css('table#myid tr:last-of-type'));
browser.executeScript("return arguments[0].offsetTop;", lastRow.getWebElement()).then(function (offset) {
browser.executeScript('arguments[0].scrollTop = arguments[1];', div.getWebElement(), offset).then(function() {
// assertions
});
});
Or, for getting a dictionary of all element attributes (python):
driver.execute_script('var items = {}; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;', element)
But, WebDriver API also has execute_async_script() which I haven't personally used.
What use cases does it cover? When should I use execute_async_script() instead of the regular execute_script()?
The question is selenium-specific, but language-agnostic.
When should I use execute_async_script() instead of the regular execute_script()?
When it comes to checking conditions on the browser side, all checks you can perform with execute_async_script can be performed with execute_script. Even if what you are checking is asynchronous. I know because once upon a time there was a bug with execute_async_script that made my tests fail if the script returned results too quickly. As far as I can tell, the bug is gone now so I've been using execute_async_script but for months beforehand, I used execute_script for tasks where execute_async_script would have been more natural. For instance, performing a check that requires loading a module with RequireJS to perform the check:
driver.execute_script("""
// Reset in case it's been used already.
window.__selenium_test_check = undefined;
require(["foo"], function (foo) {
window.__selenium_test_check = foo.computeSomething();
});
""")
result = driver.wait(lambda driver:
driver.execute_script("return window.__selenium_test_check;"))
The require call is asynchronous. The problem with this though, besides leaking a variable into the global space, is that it multiplies the network requests. Each execute_script call is a network request. The wait method works by polling: it runs the test until the returned value is true. This means one network request per check that wait performs (in the code above).
When you test locally it is not a big deal. If you have to go through the network because you are having the browsers provisioned by a service like Sauce Labs (which I use, so I'm talking from experience), each network request slows down your test suite. So using execute_async_script not only allows writing a test that looks more natural (call a callback, as we normally do with asynchronous code, rather than leak into the global space) but it also helps the performance of your tests.
result = driver.execute_async_script("""
var done = arguments[0];
require(["foo"], function (foo) {
done(foo.computeSomething());
});
""")
The way I see it now is that if a test is going to hook into asynchronous code on the browser side to get a result, I use execute_async_script. If it is going to do something for which there is no asynchronous method available, I use execute_script.
Here's the reference to the two APIs (well it's Javadoc, but the functions are the same), and here's an excerpt from it that highlights the difference
[executeAsyncScript] Execute an asynchronous piece of JavaScript in
the context of the currently selected frame or window. Unlike
executing synchronous JavaScript, scripts executed with this method
must explicitly signal they are finished by invoking the provided
callback. This callback is always injected into the executed function
as the last argument.
Basically, execSync blocks further actions being performed by the selenium browser, while execAsync does not block and calls on a callback when it's done.
Since you've worked with protractor, I'll use that as example.
Protractor uses executeAsyncScript in both get and waitForAngular
In waitForAngular, protractor needs to wait until angular announces that all events settled. You can't use executeScript because that needs to return a value at the end (although I guess you can implement a busy loop that polls angular constantly until it's done). The way it works is that protractor provides a callback, which Angular calls once all events settled, and that requires executeAsyncScript. Code here
In get, protractor needs to poll the page until the global window.angular is set by Angular. One way to do it is driver.wait(function() {driver.executeScript('return window.angular')}, 5000), but that way protractor would pound at the browser every few ms. Instead, we do this (simplified):
functions.testForAngular = function(attempts, callback) {
var check = function(n) {
if (window.angular) {
callback('good');
} else if (n < 1) {
callback('timedout');
} else {
setTimeout(function() {check(n - 1);}, 1000);
}
};
check(attempts);
};
Again, that requires executeAsyncScript because we don't have a return value immediately. Code here
All in all, use executeAsyncScript when you care about a return value in a calling script, but that return value won't be available immediately. This is especially necessary if you can't poll for the result, but must get the result using a callback or promise (which you must translate to callback yourself).
The context
We have an Ember-based app which handles large amount of structured data (Business process models).
Important! We would really like to keep our app offline-able, as far as possible.
The need
While we only have to display these data, edit them, and so on, there is no show-stopper in the radar...
But now, we want to apply processing on these models: validity checking, paths finding... and several kind of time/memory consuming algorithms.
The problem
We could process algorithms on the server, but that would kill the app's offline mode.
We have thought about web workers to avoid freezing application and process algorithms in the background, but we faced a major issue: data duplication when passing the data to the worker.
Using Transferable Objects would make the app lose the ownership (and the data) during at least the computation, so it does not seem viable.
How would you handle this problem? Is our only way out the use of a "coroutine-like" implementation of our algorithms? Any clue?
If your major concern is not to freeze UI during lengthy javascript processing you developed, you can refactor loop bodies into sequential steps, such that each step call its next by using window.setTimeout. This technique allows the (single) thread to process UI events between each interaction:
var pr = function(x) {console.log(x)};
var COUNT=3;
// original regular javascript loop
for(var i=0; i<COUNT; i++) {
var msg = "current index is (" + i + ")";
pr(msg);
}
// step-by-step sequential calls
var body = function(i) {
var msg = "non-blocking for: index is (" + i + ")";
pr(msg);
}
nonBlockingFor(body, 4);
The function nonBlockingFor calls the first argument (as a function) the number of times passed as second argument. It's definition follows:
// function constructor
var nonBlockingFor = (function() {
function _run(context) {
if(context.idx > context.max) return;
context.fnc(context.idx++);
window.setTimeout((function(){ _run(context)}), 1);
}
return (function _start(ufn, uqt, runId) {
_run({idx: 0, max: uqt -1, fnc: ufn || (function(){}), runId: runId});
});
})();
Please note that this is a very simplified function and it can be improved to handle other multi-thread related issues -- i.e: waiting for the threads to finish (join). I hope this code helps you. Please let me know if you like this approach to the problem, I could spend some time improving my suggestion, if you like.
Long time has passed, but still : a solution may be http://jscex.info/
Javascript is single threaded in nature, and it's a design choice cause multithreading is a hard topic 99% of the casual javascript developers would not handle properly.
Workers are the only way to obtain another thread and not block the UI, but to make them usable without the dangerous side effects of real multithreading, they run in a completely separated context, as you noticed. So they are more similar to calling an external command passing command line parameters than spawning another thread.
So, working in "async" mode is the only solution right now, but since you are not waiting for a click of a button or a remote connection to complete, the only async event you can bind to is the tick of a timer, which leads to the poor code style that plagues long running operations in js.
There is however a small library, that I found to be very interesting and quite unknown, that (despite it's poor website) is able to "convert" on the fly a beautifully written procedural code to the mess of timers and functions the async model inherently requires : http://jscex.info/
As in windows 3.1, you just need to "yield" ( $await(Jscex.Async.sleep(50)); ) some time to the browser so that it does not completely freeze. It will actually freeze under the hood, but if you yield frequently enough no one will ever notice :) (afterall, that is how multitasking still works inside each single core of your cpu, very small slices of time during which the CPU is 100% working on a single set of instructions .. take that to 20 ms an no one can tell).
I think that could help you "produce" a coroutine-like JS without actually "writing" such code, but delegating to a "precompiler" the work of messing it up.
I would like to thread some Javascript code while both the main process and thread are free to update the browser UI.
For example:
function StartStuff() {
StartThreadedCode();
// do more work and update the UI while StartThreadedCode() does its work
}
function StartThreadedCode() {
// do stuff (do work and update the UI)
}
Is it possible?
There are two main ways to achieve "multithreading" in Javascript. The first way is a cross-browser solution, that would also work in older browsers, but is more complicated to implement.
The idea behind it is that you give the UI some time to update every once in awhile. Since there's no synchronous sleep function in Javascript, the only way to achieve this is to use setTimeout (or setInterval with a little bit more complicate logic) to delay the execution of every loop of your complex calculations. This would give the browser some time to update the UI between loops, giving the visual effect of multiple things happening simultaneously. A few ms should be more than enough for the UI to reflect the latest changes.
It has it's drawbacks of course, and can be quite difficult to implement if there are multiple actions the user might want to do while the background calculations are being performed. Also it can drastically slow down the whole background calculation, since it's delayed a few ms now and then. In specific cases, however, it does the trick and performs well.
The second option would be to use web workers, that are basically Javascript scripts running independently in the background, like a thread. It's much easier to implement, you only have to worry about messaging between main code and background workers, so your whole application isn't affected as much. You can read about using them from the link posted by Mic https://developer.mozilla.org/en/Using_web_workers. The greatest drawback of web workers is their support by browsers, which you can see at http://caniuse.com/#search=worker There's no possible workaround for IE <9 or mobile browsers that truly simulate the effect, so there's not much you can do about those browsers, but then again, the benefits of modern browsers might outweigh poor IE support. This, of course, depends on your application.
Edit: Im not sure whether I explained the first concept clearly enough, so I decided to add a small example. The following code is functionally equivalent to:
for (var counter = 0; counter < 10; counter++) {
console.log(counter);
}
But instead of logging 0-9 in quick succession, it delays 1s before executing the next iteration of the loop.
var counter = 0;
// A single iteration of your calculation function
// log the current value of counter as an example
// then wait before doing the next iteration
function printCounter() {
console.log(counter);
counter++;
if (counter < 10)
setTimeout(printCounter, 1000);
}
// Start the loop
printCounter();
As of 2009 (FF 3.5/Gecko 1.9.1) a new Web API was added that is called Web Workers. It works also on Chrome 4+, Opera 10.6+ and IE10+.
The worker is basically a background thread that runs in a separate process.
The communication between the master process (eg. your UI's main thread) and the slave process (the background thread, the worker) is established with the aid of a generic PostMessage/onmessage function where you can exchange whatever data you like between the two parties.
It is worth mentioning that every single worker is assigned to a different core. For instance by creating 4 different workers (that do a long-running computation) on a quad-processor you are going to see all the 4 CPU-cores like 100% while the main-script is still idling and thus responding to your UI events (look at this example).
A basic example:
main-script.js
if ("function" !== typeof window.Worker) {
throw "Your browser doesn't support Web Workers";
}
var thread = new Worker("background-thread.js");
thread.onmessage = function(e) {
console.log("[A] : I received a " + e.data + " :-P");
};
thread.onerror = function(e) {
console.log(e);
};
console.log("[A] : I'm sending a PING :-)");
thread.postMessage("PING");
background-thread.js
onmessage = function(e) {
console.log("[B] : I receveid a " + e.data + " :-)");
console.log("[B] : I will respond with a PONG ;-)");
postMessage("PONG");
};
The above example should produce the following output at your browser's console:
[A] : I'm sending a PING :-)
[B] : I receveid a PING :-)
[B] : I will respond with a PONG ;-)
[A] : I received a PONG :-P
So happy PING-ing to your background script!
Javascript is single threaded language, but you can do some tricks to imitate multithreading:
http://www.nczonline.net/blog/2009/08/11/timed-array-processing-in-javascript/
http://www.nczonline.net/blog/2011/09/19/script-yielding-with-setimmediate/
http://www.nczonline.net/blog/2011/05/03/better-javascript-animations-with-requestanimationframe/
function takesTime(){
for (var i = 0; i<some_very_large_number; i++){
//do something synchronous
}
console.log('a');
}
takesTime();
console.log('b');
This prints:
a
b
How would you make it print:
b
a
for (var i = 0; i < someVeryLargeNumber; ++i) {
setTimeout(function () {
//do something synchronous
}, 0);
}
Also see setZeroTimeout to gain a few milliseconds each loop, although the work people are doing there seems to be browser-based.
I see this is tagged node.js, so I'll answer it from that perspective: you shouldn't. Usually, if you're blocking, it will be: network-bound (you should be using and/or reusing network libraries around asynchronous methods), I/O-bound (you should be using and/or reusing I/O libraries), or CPU-bound. You haven't provided any context for what the long-running task is, and given that you have a loop invariant containing some_very_large_number, I'm assuming you're imagining some CPU-intensive task iterating over a large field.
If you're actually CPU-bound, you should rethink your strategy. Node only lives on one core, so even if you were able to use multithreading, you'd really just be spinning your wheels, as each request would still require a certain amount of CPU time. If you actually intend on doing something computationally-intensive, you may want to look into using a queuing system, and having something else processing the data that's better designed for crunching it.
Javascript is event-based, and everything happens in a single thread. The way for you to make it "asynchronous" is to use a timeout (setTimeout()).
You can use web workers to achieve your objective, but you'll require a separate js file, and you'll have to add plumbing code to post messages and handle those messages.
node.js doesn't support web workers natively, but an implementation is available at:
https://github.com/cramforce/node-worker/
Otherwise, it's similar to the following code:
var pid = require('child_process').spawn('node', ['childScript.js'])
pid.stdout.on('data', function(data) {
console.log(data);
});
console.log('b');
childScript.js
for (var i = 0; i < some_very_large_number; i++) {
// do something synchronous
}
console.log('a');