I am using Raphael.js to visualize a convex hull algorithm.
However I want to be able to step through the different parts of the code (or use something like sleep()/delay()). However, I can't see a way of accomplishing this using setTimeOut(). Any ideas?
For example:
sort(points);
//sleep(...)/delay(...)/pause until click?
for(...) {
message('Foo thing');
//sleep(...)/delay(...)/pause until click?
while() {
message('Comparing points');
//sleep(...)/delay(...)/pause until click?
}
}
In JavaScript there is no way to suspend code execution with sleep function. Executing JavaScript code is designed to be non-blocking.
Solution with using debugger keyword works on Chrome as well. You just have to open Developer Tools.
I prepared demo which works in different way. It simulates sleep function using setInterval and does not block scripts execution. However, it involves some additional code.
Let's assume that we have initial code:
var arr = [0, 1, 2, 3, 4];
function step(val) {
console.log(val);
}
for (var i = 0, len = arr.length; i < len; i++) {
step(arr[i]);
}
Now, we'd like to rewrite it so that each log shows after one second:
var arr = [0, 1, 2, 3, 4],
steps = [];
function step(val) {
console.log(val);
}
for (var i = 0, len = arr.length; i < len; i++) {
steps[i] = step.bind(null, arr[i]);
}
var int = setInterval(function() {
var fun = steps.shift();
if(!fun) {
clearInterval(int);
return;
}
fun();
}, 1000);
Let me explain it a little bit. Firstly, I define steps array, where I put new functions with bound arguments. bind function basically creates new function with arguments which are bound to provided values. More details on MDN page.
Example:
function step(a) { console.log(a); }
var step1 = step.bind(null, 1);
// now step1 is like `var step1 = function() { console.log(1); }`
In for loop I create and put new functions using bind. The last step is to extract these functions from steps array, starting from beginning (using Array.prototype.shift method), and execute them with interval equal to 1 second.
I know it's not a direct solution of your problem, but I hope it helps you convert your code properly. If you decide to do so, I advise to convert code blocks within for and while loops to functions. It simplifies conversion a little bit.
You could try to use the debugging tools available on your browser. If you are on chrome, enable the developer tools by pressing Shift + Ctrl + I. If you are on firefox, you could download install the firebug extension. Once you have done this, you can step through your code by putting in place a breakpoint. This is done by putting the 'debugger;' keyword at the javascript point where you want to begin stepping through. E.g
sort(points);
debugger
for(...) {
message('Foo thing');
debugger;
while() {
message('Comparing points');
debugger;
}
}
Maybe you could wait for a button click and then when the click has happened you could step one line of code in?
set a onclick listener for the button and set the variable continue = true;
after the piece of code has executed and you want to wait for the next piece of code to run you could use.
//code just executed
while(continue == false) sleep(10);
continue = false;
//next code to be executed
while(continue == false) sleep(10);
continue = false;
//more code....
there is probably a better solution than this so don't take this code as the best unless its your only answer.
Related
I am working on a E2E test for a single-page web application in Angular2.
There are lots of clickable tags (not redirected to other pages but has some css effect when clicking) on the page, with some logic between them. What I am trying to do is,
randomly click a tag,
check to see the the response from the page is correct or not (need to grab many components from the web to do this),
then unclick it.
I set two const as totalRound and ITER, which I would load the webpage totalRound times, then within each loading page, I would randomly choose and click button ITER times.
My code structure is like:
let totalRound: number = 10;
let ITER: number = 100;
describe('XX Test', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
describe('Simulate User\'s Click & Unclick',() => {
for(let round = 0; round < totalRound; round++){
it('Click Simulation Round ' + round, () =>{
page.navigateTo('');
let allTagFinder = element.all(by.css('someCSS'));
allTagFinder.getText().then(function(tags){
let isMatched: boolean = True;
let innerTurn = 0;
for(let i = 0; i < ITER; i++){
/* Randomly select a button from allTagFinder,
using async func. eg. getText() to get more info
about the page, then check if the logic is correct or not.
If not correct, set isMatchTemp, a local variable to False*/
isMatched = isMatched && isMatchTemp;
innerTurn += 1;
if(innerTurn == ITER - 1){
expect(isMatched).toEqual(true);
}
}
});
});
}
});
});
I want to get a result after every ITER button checks from a loading page. Inside the for loop, the code is nested for async functions like getText(), etc..
In most time, the code performs correctly (looks the button checkings are in sequential). But still sometimes, it seems 2 iterations' information were conflicted. I guess there is some problem with my code structure for the async.
I thought JS is single-thread. (didn't take OS, correct me if wrong) So in the for loop, after all async. function finish initialization, all nested async. function (one for each loop) still has to run one by one, as what I wish? So in the most, the code still perform as what I hope?
I tried to add a lock in the for loop,
like:
while(i > innerTurn){
;
}
I wish this could force the loop to be run sequentially. So for the async. func from index 1 to ITER-1, it has to wait the first async. finish its work and increment the innerTurn by 1. But it just cannot even get the first async. (i=0) back...
Finally I used promise to solve the problem.
Basically, I put every small sync/async function into separate promises then use chaining to make sure the later function will only be called after the previous was resolved.
For the ITER for loop problem, I used a recursion plus promise approach:
var clickTest = function(prefix, numLeft, ITER, tagList, tagGsLen){
if(numLeft == 0){
return Promise.resolve();
}
return singleClickTest(prefix, numLeft, ITER, tagList, tagGsLen).then(function(){
clickTest(prefix, numLeft - 1, ITER, tagList, tagGsLen);
}).catch((hasError) => { expect(hasError).toEqual(false); });
}
So, each single clicking test will return a resolve signal when finished. Only then, the next round will be run, and the numLeft will decrease by 1. The whole test will end when numLeft gets to 0.
Also, I tried to use Python to rewrite the whole program. It seems the code can run in sequential easily. I didn't met the problems in Protractor and everything works for my first try. The application I need to test has a relatively simple logic so native Selenium seemed to be a better choice for me since it does not require to run with Frond-end code(just visit the webapp url and grab data and do process) and I am more confident with Python.
I have a block of code that executes when a button is clicked. The code uses a loop that sometimes takes a while to complete. When the user clicks the button, I want the cursor to change a "wait" cursor before the loop begins. Once the loop is finished, the cursor should return to normal.
What is actually happening (in Chrome for Windows at least) is that the style doesn't get updated until after the loop. It seems to be a quirk of how buttons work. I really don't know. I'm out of guesses!
A sample fiddle: http://jsfiddle.net/ra51npjr/1/ (it just uses console.log to execute "something"... you might need to change how many times the loop runs depending on how zippy or slow your machine is).
Sample HTML:
<div class="fakebody">
<button id="foo">Foo</button>
</div>
Sample CSS:
.fakeBody {
height: 1000px;
width: 100%;
}
.wait {
cursor: wait !important;
}
Sample JavaScript:
$('#foo').on('click', function (e) {
$('.fakebody').addClass('wait');
for (i = 0; i < 10000; i++) {
console.log(i);
}
$('.fakebody').removeClass('wait');
});
--
Here are my ASSUMPTIONS on how the script should work:
The click happens, which fires up the code. Indeed, if I log "started!" inside the code block, it will correctly log that it has started
The cursor should be a wait cursor so long as it is hovering anywhere over "fakebody".
The for loop is just a simple way to kill a few seconds to see the effect. Feel free to substitute any other loop that takes a while to complete
At the end of the loop, the cursor is no longer a wait cursor
What is actually happening:
The loop executes
At the end of the loop, the cursor turns to a "wait" cursor and then instantly back to a regular cursor. The change doesn't happen until the loop is complete
Does anybody know a technique or workaround to get the cursor to change before the loop starts instead of only after it is finished? Is this known behaviour that I need to educate myself about (and if so, do you know where I should start looking?)
This is a common issue in JavaScript. This question may provide some deeper insight, but essentially the point is that synchronous JavaScript execution must finish before the browser can perform other actions (like updating the view).
Because .addClass, the for loop, and .removeClass all occur synchronously, the browser doesn't get a chance to redraw anything. A technique that is often used in these cases is to setTimeout with a timeout of 0, which essentially just "yields" control back to the browser.
$('.fakebody').addClass('wait');
setTimeout(function() {
for (i = 0; i < 10000; i++) {
console.log(i);
}
$('.fakebody').removeClass('wait');
}, 0);
If this is a common pattern, you could potentially extract it out to a function (which would also help improve readability) that wraps the async setTimeout. Here's a simple example:
/**
* Wraps a long-running JavaScript process in a setTimeout
* which yields to allow the browser to process events, e.g. redraw
*/
function yieldLongRunning(preFn, fn, postFn, ctx) {
if (arguments.length <= 2) {
ctx = fn; fn = preFn;
preFn = postFn = function() {};
}
preFn.call(ctx);
setTimeout(function() {
fn.call(ctx);
postFn.call(ctx);
}, 0);
}
And use it like so:
yieldLongRunning(function() {
$('.fakebody').addClass('wait');
},
function() {
for (i = 0; i < 10000; i++) {
console.log(i);
}
},
function() {
$('.fakebody').removeClass('wait');
});
As a side point, note that setTimeout(..., 0) simply queues the function in the browser's event loop, alongside other queued JavaScript functions, as well as other types of events (like redraws). Thus, no setTimeout call is guaranteed to run precisely at the given time - the timeout argument is simply a lower-bound (and, in fact, there is a minimum timeout of 4ms specified by HTML5 spec, which browsers use to prevent infinite timeout loops; you can still use 0, though, and the browser will add it to the event queue after the minimum delay).
I think you should try to force a redraw by hiding + showing the parent element.
Try this:
document.getElementById('fakebody').style.display = 'none';
document.getElementById('fakebody').style.display = 'block';
Before and after the loop (i.e. when you want the child element "foo" to refresh.
EDIT: Since you're using jquery you could do this:
$('#fakebody').hide().show(0);
Demo - Use queue & dequeue to construct an order of what should happen when in jQuery.
$('#foo').on('click', function (e) {
$('.fakebody').addClass('wait').queue(function(n) {
for (i = 0; i < 10000; i++) { console.log(i); }
}).removeClass('wait').dequeue();
});
I am not entirely sure how to phrase this question, but basically, I have a class, button that on its click should call the function passed to it.
button = function(...,callBack) {
//...
this._cb = callBack;
}
button.prototype.callBack = function(e) {
//...
this._cb();
}
and then somewhere else
//on canvas click
e.target.callBack(e);
(I hope this is about the right amount of background, I can give more if needed)
So the issue I am running into is when I dynamically instantiate the buttons such that their callbacks use data from an array. i.e.
for (var i = 0; i < levels.length; i++) {
buttons[buttons.length] = new button(..., function() {drawLevel(levels[i])});
}
Then when they are clicked, they run that callback code and try to find some random value for i (probably a for-loop that didn't use var) and runs that level.
My question is, how can I (without using eval) circumvent this problem.
Thanks!
I'm not 100% clear on what you're asking, but it looks like you're going to be getting the wrong value for i in the anonymous function you're creating in the loop (it will always be levels.length)
Way around this is to have a different scope for every function created, with the i in each scope being a copy of the i in the loop
buttons[buttons.length] = new button(..., (function(i){
return function() {drawLevel(levels[i])};
})(i));
I am trying to make a basic enough page that allows the user to execute a php script by clicking a button. Each button will have a loading spinner popup on clicking.
My problem is, on clicking one button and then clicking another, both spinners close at the exact same time even though the second may still be processing.
Does anyone know how to make these spinners truly asynchronous ? Thanks so much in advance, its killing me.
JS:
function test(element){
var append = "#";
var test = append.concat(element);
document.getElementById(element).style.visibility='visible';
$.ajax({url:"test.php",success:function(result){
hide(element);
}
});
};
function hide(element){
document.getElementById(element).style.visibility='hidden';
};
</script>
HTML:
<html>
<?
$index = 0;
$myArray = array ("1", "2", "3", "4", "5");
for($index = 0; $index < 5; $index++){?>
<button onclick="test('<?echo $myArray [$index];?>')">Start</button>
<img id="<?echo $myArray [$index];?>" src="images/loader.gif"
style="visibility:hidden"/>
<br><br>
<?}?>
</html>
I would implement a counter. Each time you show the loading indicator, add one to the counter and each time you want to hide it, subtract one. Then monitor the counter and whenever it is above zero show the loading indicator and when at zero hide it. Make sense?
Something like the following (untested) code might do the trick and it neatly means you can avoid worrying about the spinner at all in ajax requests:
var spinningAjax = (function() { // use of the closure created by an immediate function gives us the scope to create a persistant counter variable
var counter = 0;
$(document).ajaxComplete(function() {
counter--;
if (counter === 0) {
showSpinner(false);
}
});
return function(settings) {
counter++;
showSpinner(true);
$.ajax(settings);
}
})();
var showSpinner(bool) {
// I'll leave this up to you as it looks like your posted html / js is for example purposes rather than replicating your actual site
};
EDIT: Ok, having seen the comments to another answer, I realise this doesn't quite solve the situation you're in. I'll have a think and see if I can do better
EDIT2: I think this (still untested, unfortunately) code may be what you require. Please let me know in the comments if you have any issues.
var spinningAjax = (function() { // closure of immediate function lets us create a persistant array of the counters for each spinner
var counter = []; // an array to hold the counters for each spinner
$(document).ajaxComplete(function(event, xhr, settings) { // called whenever any ajax request is completed
if (typeof settings.ajaxGroup !== 'undefined') { // only update the counters if an ajaxGroup has been provided
counter[settings.ajaxGroup]--;
if (counter[settings.ajaxGroup] === 0) {
showSpinner(false, settings.ajaxGroup); // hide spinner when all requests connected with the spinner have been completed
}
}
});
return function(settings) { // this is the function actually assigned to the variable spinningAjax as a result of the immediate function
counter[settings.ajaxGroup] = counter[settings.ajaxGroup] ? counter[settings.ajaxGroup]+1 : 1; // can't just use the ++ operator as this property might not be defined yet
showSpinner(true, settings.ajaxGroup);
$.ajax(settings);
}
})();
var showSpinner(bool, spinnerIdentifier) {
// I'll leave this up to you as it looks like your posted html / js is for example purposes rather than replicating your actual site
};
I've only found rather complicated answers involving classes, event handlers and callbacks (which seem to me to be a somewhat sledgehammer approach). I think callbacks may be useful but I cant seem to apply these in the simplest context. See this example:
<html>
<head>
<script type="text/javascript">
function myfunction() {
longfunctionfirst();
shortfunctionsecond();
}
function longfunctionfirst() {
setTimeout('alert("first function finished");',3000);
}
function shortfunctionsecond() {
setTimeout('alert("second function finished");',200);
}
</script>
</head>
<body>
Call my function
</body>
</html>
In this, the second function completes before the first function; what is the simplest way (or is there one?) to force the second function to delay execution until the first function is complete?
---Edit---
So that was a rubbish example but thanks to David Hedlund I see with this new example that it is indeed synchronous (along with crashing my browser in the test process!):
<html>
<head>
<script type="text/javascript">
function myfunction() {
longfunctionfirst();
shortfunctionsecond();
}
function longfunctionfirst() {
var j = 10000;
for (var i=0; i<j; i++) {
document.body.innerHTML += i;
}
alert("first function finished");
}
function shortfunctionsecond() {
var j = 10;
for (var i=0; i<j; i++) {
document.body.innerHTML += i;
}
alert("second function finished");
}
</script>
</head>
<body>
Call my function
</body>
</html>
As my ACTUAL issue was with jQuery and IE I will have to post a separate question about that if I can't get anywhere myself!
Well, setTimeout, per its definition, will not hold up the thread. This is desirable, because if it did, it'd freeze the entire UI for the time it was waiting. if you really need to use setTimeout, then you should be using callback functions:
function myfunction() {
longfunctionfirst(shortfunctionsecond);
}
function longfunctionfirst(callback) {
setTimeout(function() {
alert('first function finished');
if(typeof callback == 'function')
callback();
}, 3000);
};
function shortfunctionsecond() {
setTimeout('alert("second function finished");', 200);
};
If you are not using setTimeout, but are just having functions that execute for very long, and were using setTimeout to simulate that, then your functions would actually be synchronous, and you would not have this problem at all. It should be noted, though, that AJAX requests are asynchronous, and will, just as setTimeout, not hold up the UI thread until it has finished. With AJAX, as with setTimeout, you'll have to work with callbacks.
I am back to this questions after all this time because it took me that long to find what I think is a clean solution :
The only way to force a javascript sequential execution that I know of is to use promises.
There are exhaustive explications of promises at : Promises/A and Promises/A+
The only library implementing promises I know is jquery so here is how I would solve the question using jquery promises :
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
function myfunction()
{
promise = longfunctionfirst().then(shortfunctionsecond);
}
function longfunctionfirst()
{
d = new $.Deferred();
setTimeout('alert("first function finished");d.resolve()',3000);
return d.promise()
}
function shortfunctionsecond()
{
d = new $.Deferred();
setTimeout('alert("second function finished");d.resolve()',200);
return d.promise()
}
</script>
</head>
<body>
Call my function
</body>
</html>
By implementing a promise and chaining the functions with .then() you ensure that the second function will be executed only after the first one has executed
It is the command d.resolve() in longfunctionfirst() that give the signal to start the next function.
Technically the shortfunctionsecond() does not need to create a deferred and return a promise, but I fell in love with promises and tend to implement everything with promises, sorry.
I am an old hand at programming and came back recently to my old passion and am struggling to fit in this Object oriented, event driven bright new world and while i see the advantages of the non sequential behavior of Javascript there are time where it really get in the way of simplicity and reusability.
A simple example I have worked on was to take a photo (Mobile phone programmed in javascript, HTML, phonegap, ...), resize it and upload it on a web site.
The ideal sequence is :
Take a photo
Load the photo in an img element
Resize the picture (Using Pixastic)
Upload it to a web site
Inform the user on success failure
All this would be a very simple sequential program if we would have each step returning control to the next one when it is finished, but in reality :
Take a photo is async, so the program attempt to load it in the img element before it exist
Load the photo is async so the resize picture start before the img is fully loaded
Resize is async so Upload to the web site start before the Picture is completely resized
Upload to the web site is asyn so the program continue before the photo is completely uploaded.
And btw 4 of the 5 steps involve callback functions.
My solution thus is to nest each step in the previous one and use .onload and other similar stratagems, It look something like this :
takeAPhoto(takeaphotocallback(photo) {
photo.onload = function () {
resizePhoto(photo, resizePhotoCallback(photo) {
uploadPhoto(photo, uploadPhotoCallback(status) {
informUserOnOutcome();
});
});
};
loadPhoto(photo);
});
(I hope I did not make too many mistakes bringing the code to it's essential the real thing is just too distracting)
This is I believe a perfect example where async is no good and sync is good, because contrary to Ui event handling we must have each step finish before the next is executed, but the code is a Russian doll construction, it is confusing and unreadable, the code reusability is difficult to achieve because of all the nesting it is simply difficult to bring to the inner function all the parameters needed without passing them to each container in turn or using evil global variables, and I would have loved that the result of all this code would give me a return code, but the first container will be finished well before the return code will be available.
Now to go back to Tom initial question, what would be the smart, easy to read, easy to reuse solution to what would have been a very simple program 15 years ago using let say C and a dumb electronic board ?
The requirement is in fact so simple that I have the impression that I must be missing a fundamental understanding of Javsascript and modern programming, Surely technology is meant to fuel productivity right ?.
Thanks for your patience
Raymond the Dinosaur ;-)
In your example, the first function does actually complete before the second function is started. setTimeout does not hold execution of the function until the timeout is reached, it will simply start a timer in the background and execute your alert statement after the specified time.
There is no native way of doing a "sleep" in JavaScript. You could write a loop that checks for the time, but that will put a lot of strain on the client. You could also do the Synchronous AJAX call, as emacsian described, but that will put extra load on your server. Your best bet is really to avoid this, which should be simple enough for most cases once you understand how setTimeout works.
I had the same problem, this is my solution:
var functionsToCall = new Array();
function f1() {
$.ajax({
type:"POST",
url: "/some/url",
success: function(data) {
doSomethingWith(data);
//When done, call the next function..
callAFunction("parameter");
}
});
}
function f2() {
/*...*/
callAFunction("parameter2");
}
function f3() {
/*...*/
callAFunction("parameter3");
}
function f4() {
/*...*/
callAFunction("parameter4");
}
function f5() {
/*...*/
callAFunction("parameter5");
}
function f6() {
/*...*/
callAFunction("parameter6");
}
function f7() {
/*...*/
callAFunction("parameter7");
}
function f8() {
/*...*/
callAFunction("parameter8");
}
function f9() {
/*...*/
callAFunction("parameter9");
}
function callAllFunctionsSy(params) {
functionsToCall.push(f1);
functionsToCall.push(f2);
functionsToCall.push(f3);
functionsToCall.push(f4);
functionsToCall.push(f5);
functionsToCall.push(f6);
functionsToCall.push(f7);
functionsToCall.push(f8);
functionsToCall.push(f9);
functionsToCall.reverse();
callAFunction(params);
}
function callAFunction(params) {
if (functionsToCall.length > 0) {
var f=functionsToCall.pop();
f(params);
}
}
If you don't insist on using pure Javascript, you can build a sequential code in Livescript and it looks pretty good. You might want to take a look at this example:
# application
do
i = 3
console.log td!, "start"
<- :lo(op) ->
console.log td!, "hi #{i}"
i--
<- wait-for \something
if i is 0
return op! # break
lo(op)
<- sleep 1500ms
<- :lo(op) ->
console.log td!, "hello #{i}"
i++
if i is 3
return op! # break
<- sleep 1000ms
lo(op)
<- sleep 0
console.log td!, "heyy"
do
a = 8
<- :lo(op) ->
console.log td!, "this runs in parallel!", a
a--
go \something
if a is 0
return op! # break
<- sleep 500ms
lo(op)
Output:
0ms : start
2ms : hi 3
3ms : this runs in parallel! 8
3ms : hi 2
505ms : this runs in parallel! 7
505ms : hi 1
1007ms : this runs in parallel! 6
1508ms : this runs in parallel! 5
2009ms : this runs in parallel! 4
2509ms : hello 0
2509ms : this runs in parallel! 3
3010ms : this runs in parallel! 2
3509ms : hello 1
3510ms : this runs in parallel! 1
4511ms : hello 2
4511ms : heyy
In javascript, there is no way, to make the code wait. I've had this problem and the way I did it was do a synchronous SJAX call to the server, and the server actually executes sleep or does some activity before returning and the whole time, the js waits.
Eg of Sync AJAX: http://www.hunlock.com/blogs/Snippets:_Synchronous_AJAX
I tried the callback way and could not get this to work, what you have to understand is that values are still atomic even though execution is not. For example:
alert('1'); <--- these two functions will be executed at the same time
alert('2'); <--- these two functions will be executed at the same time
but doing like this will force us to know the order of execution:
loop=2;
total=0;
for(i=0;i<loop;i++) {
total+=1;
if(total == loop)
alert('2');
else
alert('1');
}
Another way to look at this is to daisy chain from one function to another.
Have an array of functions that is global to all your called functions, say:
arrf: [ f_final
,f
,another_f
,f_again ],
Then setup an array of integers to the particular 'f''s you want to run, e.g
var runorder = [1,3,2,0];
Then call an initial function with 'runorder' as a parameter, e.g.
f_start(runorder);
Then at the end of each function, just pop the index to the next 'f' to execute off the runorder array and execute it, still passing 'runorder' as a parameter but with the array reduced by one.
var nextf = runorder.shift();
arrf[nextf].call(runorder);
Obviously this terminates in a function, say at index 0, that does not chain onto another function.
This is completely deterministic, avoiding 'timers'.
Put your code in a string, iterate, eval, setTimeout and recursion to continue with the remaining lines. No doubt I'll refine this or just throw it out if it doesn't hit the mark. My intention is to use it to simulate really, really basic user testing.
The recursion and setTimeout make it sequential.
Thoughts?
var line_pos = 0;
var string =`
console.log('123');
console.log('line pos is '+ line_pos);
SLEEP
console.log('waited');
console.log('line pos is '+ line_pos);
SLEEP
SLEEP
console.log('Did i finish?');
`;
var lines = string.split("\n");
var r = function(line_pos){
for (i = p; i < lines.length; i++) {
if(lines[i] == 'SLEEP'){
setTimeout(function(){r(line_pos+1)},1500);
return;
}
eval (lines[line_pos]);
}
console.log('COMPLETED READING LINES');
return;
}
console.log('STARTED READING LINES');
r.call(this,line_pos);
OUTPUT
STARTED READING LINES
123
124
1 p is 0
undefined
waited
p is 5
125
Did i finish?
COMPLETED READING LINES