I am working on a tool that allows users to enter a regular expression for a find&replace, and then my tool will execute that find&replace and return the changed text. However, I recently ran into a situation where the find&replace simply froze, so I decided it would probably be best to somehow detect issues with regular expression matching, and abort after a certain amount of time has passed.
I've checked around, and what I was able to find using this answer was that the problem I'm experiencing was called 'catastrophic backtracking'. That's ideal to know, because that way I can make a minimal working example of where it goes wrong, however not ideal if the solution to change the regular expression isn't possible, because I have no control over the user's regex input (and there's no way I can write an advanced enough regex parser to limit the user's regex usage to exclude situations like this).
So in an attempt to solve this, I tried using promises, as suggested in this answer. I've made the 'catastrophic' match string in this example just long enough for the effect to hang my tab for a few seconds, without completely crashing the tab. Different computer specs may see different results though, I'm not sure.
Just one heads-up: Executing this code might freeze your current tab. PLEASE make sure you do not have a partial answer written when executing this code, as it might cause loss of work.
var PTest = function () {
return new Promise(function (resolve, reject) {
setTimeout(function() {
reject();
}, 100)
"xxxxxxxxxxxxxxxxxxxxxxxxx".match(/(x+x+)+y/)
resolve();
});
}
var myfunc = PTest();
myfunc.then(function () {
console.log("Promise Resolved");
}).catch(function () {
console.log("Promise Rejected");
});
On my computer, this causes the tab to freeze for about 4 seconds before showing "Promise Resolved" in the console.
My question now is: is it at all possible to "abort" the execution of a script like this, if execution takes too long (in the example: over 0.2 seconds)? I'd rather kill the regex find&replace than completely crash the tool, causing loss of work for the user.
I recommend using a Web Worker since it will run in its own sandbox: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
The Web Worker is its own script that you need to include in your JavaScript, such as:
var worker = new Worker('/path/to/run-regex.js');
The following is untested code, but should get you going.
Your run-regex.js does the (potentially long running) regex match:
function regexMatch(str, regexStr, callback) {
let regex = new RegExp(regexStr);
let result = str.match(regex);
callback(result, '');
}
onmessage = function(e) {
let data = e.data;
switch (data.cmd) {
case 'match':
regexMatch(data.str, data.regex, function(result, err) {
postMessage({ cmd: data.cmd, result: result, err: err });
});
break;
case 'replace':
//regexMatch(data.str, data.regex, data.replace, function(result, err) {
// postMessage({ cmd: data.cmd, result: result, err: err });
//});
break;
default:
break;
postMessage({ err: 'Unknown command: ' + data.cmd });
}
}
In your own script, load the Web Worker, and add an event listener:
if(window.Worker) {
const myWorker = new Worker('/path/to/run-regex.js');
myWorker.onmessage = function(e) {
let data = e.data;
if(data.err) {
// handle error
} else {
// handle match result using data.result;
}
}
function regexMatch(str, regex) {
let data = { cmd: 'match', str: str, regex: regex.toString() };
myWorker.postMessage(data);
}
regexMatch('xxxxxxxxxxxxxxxxxxxxxxxxx', /(x+x+)+y/);
} else {
console.log('Your browser does not support web workers.');
}
With this, your main JavaScript thread is non blocking while the worker is working.
In case of a long running worker, you may add code to either:
ungracefully terminate the web worker using myWorker.terminate(), then restart it -- see Is it possible to terminate a running web worker?
or, try to close() from within the web worker scope -- see JavaScript Web Worker - close() vs terminate()
I'm working on a web application project with Flask+Python on the back-end, and Javascript on the front-end. I'd like to take advantage of some of the more modern (ES6/7) styles of things, such as Promises.
I've currently been writing all my javascript using Jquery 3+. Most of the time I'm making single Ajax requests to the server at a time. I've been specifically writing my Ajax requests using $.post and .done() and .fail(), which I know is already promise-based, or promise-like. Most of my code is in the style of
do function setup stuff and checks
make single ajax request
on success
good status, run several success code bits
bad status, run failure code
on failure - run failure code
I always seem to have to account for cases of server failures + cases of server success but it returned the wrong thing, which I usually control with a status argument. I've been looking into the straight Promise syntax with then, catch, resolve, reject, and I have some questions.
Is there any advantage to me switching to this format, from what I currently have, given my simple Ajax requests?
Can it be used to simplify the way I currently write my requests and handle my failure cases?
Here is a simple login example that I have, with a function that is called when a login button is clicked.
$('#loginsubmit').on('click', this, this.login);
// Login function
login() {
const form = $('#loginform').serialize();
$.post(Flask.url_for('index_page.login'), form, 'json')
.done((data)=>{
if (data.result.status < 0) {
// bad submit
this.resetLogin();
} else {
// good submit
if (data.result.message !== ''){
const stat = (data.result.status === 0) ? 'danger' : 'success';
const htmlstr = `<div class='alert alert-${stat}' role='alert'><h4>${data.result.message}</h4></div>`;
$('#loginmessage').html(htmlstr);
}
if (data.result.status === 1){
location.reload(true);
}
}
})
.fail((data)=>{ alert('Bad login attempt'); });
}
And a typical more complex example that I have. In this case, some interactive elements are initialized when a button is toggled on and off.
this.togglediv.on('change', this, this.initDynamic);
// Initialize the Dynamic Interaction upon toggle - makes loading an AJAX request
initDynamic(event) {
let _this = event.data;
if (!_this.togglediv.prop('checked')){
// Turning Off
_this.toggleOff();
} else {
// Turning On
_this.toggleOn();
// check for empty divs
let specempty = _this.graphdiv.is(':empty');
let imageempty = _this.imagediv.is(':empty');
let mapempty = _this.mapdiv.is(':empty');
// send the request if the dynamic divs are empty
if (imageempty) {
// make the form
let keys = ['plateifu', 'toggleon'];
let form = m.utils.buildForm(keys, _this.plateifu, _this.toggleon);
_this.toggleload.show();
$.post(Flask.url_for('galaxy_page.initdynamic'), form, 'json')
.done(function(data) {
let image = data.result.image;
let spaxel = data.result.spectra;
let spectitle = data.result.specmsg;
let maps = data.result.maps;
let mapmsg = data.result.mapmsg;
// Load the Image
_this.initOpenLayers(image);
_this.toggleload.hide();
// Try to load the spaxel
if (data.result.specstatus !== -1) {
_this.loadSpaxel(spaxel, spectitle);
} else {
_this.updateSpecMsg(`Error: ${spectitle}`, data.result.specstatus);
}
// Try to load the Maps
if (data.result.mapstatus !== -1) {
_this.initHeatmap(maps);
} else {
_this.updateMapMsg(`Error: ${mapmsg}`, data.result.mapstatus);
}
})
.fail(function(data) {
_this.updateSpecMsg(`Error: ${data.result.specmsg}`, data.result.specstatus);
_this.updateMapMsg(`Error: ${data.result.mapmsg}`, data.result.mapstatus);
_this.toggleload.hide();
});
}
}
}
I know this is already roughly using promises, but can I make improvements to my code flow by switching to the Promise then catch syntax? As you can see, I end up repeating a lot of the failure case code for real failures and successful failures. Most of my code looks like this, but I've been having a bit of trouble trying to convert these into something that's like
promise_ajax_call
.then(do real success)
.catch(all failure cases)
I always use Bluebird Promises. They have a Promise.resolve function that you can utilize with ajax. One thing to know about Promises, if you throw an error in a then, it will be caught in a chained catch. One way to clean this up a bit might be something like this (keep in mind, this is pseudo)
Promise.resolve($.ajax(...some properties..))
.then((data)=>{
if(data.result.status < 0){
//throw some error
}
// process the data how you need it
})
.catch((error){
// either the ajax failed, or you threw an error in your then. either way, it will end up in this catch
});
This is a fairly weird thing, and it's hard to reproduce. Not the best state of a bug report, I apologize.
I'm using .transaction() to write a value to a location in Firebase. Here's some pseudo-code:
var ref = firebase.child('/path/to/location');
var storeSafely = function(val) {
ref.transaction(
function updateFunc(currentData) {
console.log('Attempting update: ' + JSON.stringify(val));
if (currentData) return;
return val;
},
function onTransactionCompleteFunc(err, isCommitted, snap) {
if (err) {
console.log('Error in onTransactionCompleteFunc: ' + JSON.stringify(err));
return;
}
if (! isCommitted) {
console.log('Not committed');
return;
}
ref.onDisconnect().remove();
doSomeStuff();
});
};
var doSomeStuff = function() {
// Things get done, time passes.
console.log('Cleaning up');
ref.onDisconnect().cancel();
ref.set(
null,
function onSetCompleteFunc(err) {
if (err) {
console.log('Error in onSetCompleteFunc: ' + JSON.stringify(err));
}
});
};
storeSafely(1);
// later...
storeSafely(2);
// even later...
storeSafely(3);
I'm effectively using Firebase transactions as a sort of mutex lock:
Store a value at a location via transaction.
Set the onDisconnect for the location to remove the value in case my app dies while working.
Do some stuff.
Remove the onDisconnect for the location, because I'm done with the stuff.
Remove the value at the location.
I do this every few minutes, and it all works great. Things get written and removed perfectly, and the logs show me creating the lock, doing stuff, and then releasing the lock.
The weird part is what happens hours later. Occasionally Firebase has maintenance, and my app gets a bunch of permission denied errors. At the same time this happens, I suddenly start getting a bunch of this output in the logs:
Attempting update 1
Attempting update 2
Attempting update 3
...in other words, it looks like the transactions never fully completed, and they're trying to retry now that the location can't be read any more. It's almost like there's a closure in the transaction() code that never completed, and it's getting re-executed now for some reason.
Am I missing something really important here about how to end a transaction?
(Note: I originally posted this to the Firebase Google Group, but was eventually reminded that code questions are supposed to go to Stack Overflow. I apologize for the cross-posting.)
Just a guess, but I wonder if your updateFunc() function is being called with null when your app gets the permission-denied errors from Firebase. (If so, I could believe that's part of their "Offline Writes" support.)
In any case, you should handle null as a possible state. Saving Transactional Data says:
transaction() will be called multiple times and must be able to handle
null data. Even if there is existing data in your database it may not
be locally cached when the transaction function is run.
I don't know the intricacies of Firebase's transaction mechansim, but I would try changing your .set(null) to set the value to 0 instead, change your .remove() to also set the value with .set(0), and change your line in updateFunc() to:
if (currentData === null || currentData) return;
Unfortunately, that assumes that '/path/to/location' is initially set to 0 at some point. If that's a problem, maybe you can muck around with null versus undefined. For example, it would be nice if Firebase used one of those for non-existent data and another when it's offline.
How can I exit the JavaScript script much like PHP's exit or die? I know it's not the best programming practice but I need to.
"exit" functions usually quit the program or script along with an error message as paramete. For example die(...) in php
die("sorry my fault, didn't mean to but now I am in byte nirvana")
The equivalent in JS is to signal an error with the throw keyword like this:
throw new Error();
You can easily test this:
var m = 100;
throw '';
var x = 100;
x
>>>undefined
m
>>>100
JavaScript equivalent for PHP's die. BTW it just calls exit() (thanks splattne):
function exit( status ) {
// http://kevin.vanzonneveld.net
// + original by: Brett Zamir (http://brettz9.blogspot.com)
// + input by: Paul
// + bugfixed by: Hyam Singer (http://www.impact-computing.com/)
// + improved by: Philip Peterson
// + bugfixed by: Brett Zamir (http://brettz9.blogspot.com)
// % note 1: Should be considered expirimental. Please comment on this function.
// * example 1: exit();
// * returns 1: null
var i;
if (typeof status === 'string') {
alert(status);
}
window.addEventListener('error', function (e) {e.preventDefault();e.stopPropagation();}, false);
var handlers = [
'copy', 'cut', 'paste',
'beforeunload', 'blur', 'change', 'click', 'contextmenu', 'dblclick', 'focus', 'keydown', 'keypress', 'keyup', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'resize', 'scroll',
'DOMNodeInserted', 'DOMNodeRemoved', 'DOMNodeRemovedFromDocument', 'DOMNodeInsertedIntoDocument', 'DOMAttrModified', 'DOMCharacterDataModified', 'DOMElementNameChanged', 'DOMAttributeNameChanged', 'DOMActivate', 'DOMFocusIn', 'DOMFocusOut', 'online', 'offline', 'textInput',
'abort', 'close', 'dragdrop', 'load', 'paint', 'reset', 'select', 'submit', 'unload'
];
function stopPropagation (e) {
e.stopPropagation();
// e.preventDefault(); // Stop for the form controls, etc., too?
}
for (i=0; i < handlers.length; i++) {
window.addEventListener(handlers[i], function (e) {stopPropagation(e);}, true);
}
if (window.stop) {
window.stop();
}
throw '';
}
Even in simple programs without handles, events and such, it is best to put code in a main function, even when it is the only procedure :
<script>
function main()
{
//code
}
main();
</script>
This way, when you want to stop the program you can use return.
There are many ways to exit a JS or Node script. Here are the most relevant:
// This will never exit!
setInterval((function() {
return;
}), 5000);
// This will exit after 5 seconds, with signal 1
setTimeout((function() {
return process.exit(1);
}), 5000);
// This will also exit after 5 seconds, and print its (killed) PID
setTimeout((function() {
return process.kill(process.pid);
}), 5000);
// This will also exit after 5 seconds and create a core dump.
setTimeout((function() {
return process.abort();
}), 5000);
If you're in the REPL (i.e. after running node on the command line), you can type .exit to exit.
If you don't care that it's an error just write:
fail;
That will stop your main (global) code from proceeding.
Useful for some aspects of debugging/testing.
Place the debugger; keyword in your JavaScript code where you want to stop the execution. Then open your favorite browser's developer tools and reload the page. Now it should pause automatically. Open the Sources section of your tools: the debugger; keyword is highlighted and you have the option to resume script execution.
I hope it helps.
More information at:
https://developer.mozilla.org/de/docs/Tools/Debugger
http://www.w3schools.com/js/js_debugging.asp
Javascript can be disabled in devtools: ctrl+shift+j followed cltf+shift+p then type disable javascript
Possible options that mentioned above:
window.stop(); // equivalent to the 'stop' button in the browser
debugger; // debugs
for(;;); // crashes your browser
window.location.reload(); // reloads current page
If page is loaded and you don't want to debug crash or reload:
throw new Error();
Additionally clear all timeouts
var id = window.setTimeout(function() {}, 0);
while (id--) {
window.clearTimeout(id);
}
abort DOM/XMLHttpRequest
$.xhrPool = [];
$.xhrPool.abortAll = function() {
$(this).each(function(i, jqXHR) {
jqXHR.abort();
$.xhrPool.splice(i, 1);
});
}
$.ajaxSetup({
beforeSend: function(jqXHR) { $.xhrPool.push(jqXHR); },
complete: function(jqXHR) {
var i = $.xhrPool.indexOf(jqXHR);
if (i > -1) $.xhrPool.splice(i, 1);
}
});
remove all event listeners including inline
$("*").prop("onclick", null).off();
this removes scripts and recreates elements without events
$('script').remove();
$('*').each(function(){
$(this).replaceWith($(this).clone());
});
If jQuery is not available on the webpage copy-paste source code into a console.
There're might be other stuff. Let me know in a comment.
In my case I used window.stop.
The window.stop() stops further resource loading in the current browsing context, equivalent to the 'stop' button in the browser.
Because of how scripts are executed, this method cannot interrupt its parent document's loading, but it will stop its images, new windows, and other still-loading objects.
Usage: window.stop();
(source)
In JavaScript multiple ways are there, below are some of them
Method 1:
throw new Error("Something went badly wrong!");
Method 2:
return;
Method 3:
return false;
Method 4:
new new
Method 5:
write your custom function use above method and call where you needed
Note:
If you want to just pause the code execution you can use
debugger;
I think this question has been answered, click here for more information. Below is the short answer it is posted.
throw new Error("Stop script");
You can also used your browser to add break points, every browser is similar, check info below for your browser.
For Chrome break points info click here
For Firefox break points info click here
For Explorer break points info click
For Safari break points info click here
If you're looking for a way to forcibly terminate execution of all Javascript on a page, I'm not sure there is an officially sanctioned way to do that - it seems like the kind of thing that might be a security risk (although to be honest, I can't think of how it would be off the top of my head). Normally in Javascript when you want your code to stop running, you just return from whatever function is executing. (The return statement is optional if it's the last thing in the function and the function shouldn't return a value) If there's some reason returning isn't good enough for you, you should probably edit more detail into the question as to why you think you need it and perhaps someone can offer an alternate solution.
Note that in practice, most browsers' Javascript interpreters will simply stop running the current script if they encounter an error. So you can do something like accessing an attribute of an unset variable:
function exit() {
p.blah();
}
and it will probably abort the script. But you shouldn't count on that because it's not at all standard, and it really seems like a terrible practice.
EDIT: OK, maybe this wasn't such a good answer in light of Ólafur's. Although the die() function he linked to basically implements my second paragraph, i.e. it just throws an error.
throw "";
Is a misuse of the concept but probably the only option. And, yes, you will have to reset all event listeners, just like the accepted answer mentions. You would also need a single point of entry if I am right.
On the top of it: You want a page which reports to you by email as soon as it throws - you can use for example Raven/Sentry for this. But that means, you produce yourself false positives. In such case, you also need to update the default handler to filter such events out or set such events on ignore on Sentry's dashboard.
window.stop();
This does not work during the loading of the page. It stops decoding of the page as well. So you cannot really use it to offer user a javascript-free variant of your page.
debugger;
Stops execution only with debugger opened. Works great, but not a deliverable.
If you just want to stop further code from executing without "throwing" any error, you can temporarily override window.onerror as shown in cross-exit:
function exit(code) {
const prevOnError = window.onerror
window.onerror = () => {
window.onerror = prevOnError
return true
}
throw new Error(`Script termination with code ${code || 0}.`)
}
console.log("This message is logged.");
exit();
console.log("This message isn't logged.");
This little function comes pretty close to mimicking PHP's exit(). As with the other solutions, don't add anything else.
function exit(Msg)
{
Msg=Msg?'*** '+Msg:'';
if (Msg) alert(Msg);
throw new Error();
} // exit
If you use any undefined function in the script then script will stop due to "Uncaught ReferenceError". I have tried by following code and first two lines executed.
I think, this is the best way to stop the script. If there's any other way then please comment me. I also want to know another best and simple way. BTW, I didn't get exit or die inbuilt function in Javascript like PHP for terminate the script. If anyone know then please let me know.
alert('Hello');
document.write('Hello User!!!');
die(); //Uncaught ReferenceError: die is not defined
alert('bye');
document.write('Bye User!!!');
I am using iobroker and easily managed to stop the script with
stopScript();
I know this is old, but if you want a similar PHP die() function, you could do:
function die(reason) {
throw new Error(reason);
}
Usage:
console.log("Hello");
die("Exiting script..."); // Kills script right here
console.log("World!");
The example above will only print "Hello".
Wrapp with a function
(function(){
alert('start')
return;
alert('no exec')
})
i use this piece of code to stop execution:
throw new FatalError("!! Stop JS !!");
you will get a console error though but it works good for me.
To stop script execution without any error, you can include all your script into a function and execute it.
Here is an example:
(function () {
console.log('one');
return;
console.log('two');
})();
The script above will only log one.
Before use
If you need to read a function of your script outside of the script itself, remember that (normally) it doesn't work: to do it, you need to use a pre-existing variable or object (you can put your function in the window object).
The above code could be what you don't want: put an entire script in a function can have other consequences (ex. doing this, the script will run immediately and there isn't a way to modify its parts from the browser in developing, as I know, in Chrome)
This is an example, that,
if a condition exist, then terminate the script.
I use this in my SSE client side javascript, if the
<script src="sse-clint.js" host="https://sse.host" query='["q1,"q2"]' ></script>
canot be parsed right from JSON parse ...
if( ! SSE_HOST ) throw new Error(['[!] SSE.js: ERR_NOHOST - finished !']);
... anyway the general idea is:
if( error==true) throw new Error([ 'You have This error' , 'At this file', 'At this line' ]);
this will terminate/die your javasript script
Simply create a BOOL condition ,
no need for complicated code here..
If even once you turn it to true/ or multiple times,
it will both give you one line of solution/not multiple -
basically simple as that.
Not applicable in most circumstances, but I had lots of async scripts running in the browser and as a hack I do
window.reload();
to stop everything.
This code will stop execution of all JavaScripts in current window:
for(;;);
Example
console.log('READY!');
setTimeout(()=>{
/* animation call */
div.className = "anim";
console.log('SET!');
setTimeout(()=>{
setTimeout(()=>{
console.log('this code will never be executed');
},1000);
console.log('GO!');
/* BOMB */
for(;;);
console.log('this code will never be executed');
},1000);
},1000);
#div {
position: fixed;
height: 1rem; width: 1rem;
left: 0rem; top: 0rem;
transition: all 5s;
background: red;
}
/* this <div> will never reached the right bottom corner */
#div.anim {
left: calc(100vw - 1rem);
top: calc(100vh - 1rem);
}
<div id="div"></div>
i use return statement instead of throw as throw gives error in console. the best way to do it is to check the condition
if(condition){
return //whatever you want to return
}
this simply stops the execution of the program from that line, instead of giving any errors in the console.