Global variable value not reflecting in loop - javascript

My function OAuth.getSessionInfo returns response still why does the loop goes infinite?
var resp = false;
OAuth.getSessionInfo(function(data) {
resp = true;
})
do {
console.log("waiting............")
} while (!resp);
PS: Please suggest good title for the question.. I am confused on what should be the title for question

Lets remind what multi-threading and concurrency means:
Multi-threading - doing multiple things simultaneously.
Concurrency - switching fast between multiple things, thus emulating them being done simultaneously.
Javascript neither supports the first technique nor the second one. Instead it executes block of code till the end, and then executes next block that was scheduled with setTimeout or setInterval or one that came from event handler (e.g. onclick, onload).
Now if you look at your code you can see that it can't be completed without inner function being completed, but that inner function won't be executed until the outer one completes. And that's why your application hangs. You can also try next code which demonstrates your issue:
setTimeout(function() {
x = false;
console.log("won't be invoked");
}, 0);
var x = true;
while(x) {
console.log('looping');
}
P.S. This javascript's specifics is also the reason why there is no sleep function available - it simply doesn't make any sense to stop the only code executor you have.

You are getting an infinite loop because your while loop keeps running because it doesn't have a point to stop at. The way you have it now it says do this while true. So it keeps running.

Once the loop is started, you haven't updated the value of resp. Try the following:
var resp = false;
do {
OAuth.getSessionInfo(function(data) {
if (data.sessionActive == true) {
resp = true;
} else {
resp = false;
}
});
console.log("waiting............")
} while (!resp);

Related

Run While loop in the background

i have a javascript application Angular based that runs a while loop after a user press a button it runs the loop until we get a certain number then the loop ends. currently am not able to do anything else on the UI when the loop is running is there a way to push this loop to the background so the user can continue other things on the UI.
Use angular watchers for that:
$rootscope.watch(myParam, function () {});
Or use non-blocking setInterval():
var timer = setInterval(function () {
if (myParam == 'what-i-need') {
clearInterval(timer);
}
}, 200);
You can use webworker, as sample code below (the code is not fully functional but it just to give you an idea.
(
function () {
var scope = self;
var condition = false
scope.addEventListener('message', function (event) {
var caller = event.data;
if(caller.name && caller.command && caller.command === 'TERMINATE'){
return;
}
start(caller);
}, false);
function start(){
while (condition) {
if(condition)
scope.postMessage({result:"result"});
}
}
})();
In your angularjs controller or service
if (!worker) {
worker = new $window.Worker("./online-capability-worker.js");
worker.addEventListener('message', onResponse, false);
}
function onResponse(event) {
var response = event.data;
//This is my nuber returned by worker
}
Javascript is synchronous, while event driven systems allow it to mimic an asynchronous language, your code is still running on a single thread. You could use a setTimeout to recursively call a function rather than use the while loop, that way there is time for the thread to do other things in between each iteration.
function incrementNumber(initial, destination){
if(initial < destination){
setTimeout(function(){incrementNumber(initial+1, destination}), 10);
}else{
alert('We found the number!');
}
}
I would like to point out that I agree with the use of setInterval for something as simple as changing a number, but in browsers (to the best of my knowledge still), the interval is kicked off from the time the callback is initially called, which can cause unexpected results if the callback itself has any significant execution time (say, an ajax call).

How to run javascript function in web browser only when is not proccesing that function

One of my javascript function is processing millions of data and it is called ~1 time every second from a hardware event. Then the web browser is idle in that function processing.
I tried to set a flag for running (or not running) that function:
if (!is_calculating)
is_calculating = true;
else
return;
my_function(); // do heavy stuff
is_calculating = false;
but it's not working, because it is entering into the code and the web browser enter in an idle status until is finishing. When it is returning, the flag is always OK, because it finished the // do heavy stuff
Can I do something for this behavior? I'd like to jump function execution if a flag is set.
The problem is, by default javascript runs in a single thread on browsers, so your code is executing completely before it even begins to process the next call, resulting in is_calculating always being false when the function is called. One workaround you could use (not the cleanest solution in the world), is to divide your monolithic 'heavy stuff' function into a number of smaller functions and have them call each other with setTimeout(nextFunc, 1). Having them call each other that way gives the browser a moment to do what it needs to do, and additionally call your function again if that's what it's doing. This time, because your function is called in the 'middle' of it already being executed, is_calculating is still going to be true, and the call will return at the beginning like you expect it to. Note this solution probably isn't as preferable as the Web Workers solution, but it is simpler.
function sleep(millis) {
var date = new Date()
var curDate = null
do { curDate = new Date() }
while(curDate-date < millis)
}
function reallyLong() {
if(!reallyLong.flag) {
reallyLong.flag = true
} else {
console.log("Not executing")
return
}
sleep(250)
setTimeout(reallyLong2, 1)
function reallyLong2() {
sleep(250)
setTimeout(reallyLong3, 1)
}
function reallyLong3() {
sleep(250)
setTimeout(reallyLong4, 1)
}
function reallyLong4() {
sleep(250)
console.log("executed")
reallyLong.flag = false
}
}
If you define all your consecutive functions inside the primary function, it also allows them all to access the same data simply and easily.
The only catch now is if your function was returning some value, you need to rewrite it to either return a promise (Either of your own design or using a library like Q), or accept a callback as a parameter that the last function in the 'chain' will call with the return value as a parameter.
Note that the sleep function above is a hack, and awful, and terrible, and should never be used.
By default JavaScript execution in browsers is not concurrent. This means, usually there can be only one currently executing piece of code.
You have to use Web Workers API to make you code run concurrently.

Javascript: Non-blocking way to wait until a condition is true

I have several ASP.NET UpdatePanels, each with an AsyncPostBackTrigger tied to the same button's serverside click event. Since only one UpdatePanel can be doing its thing at a time, I use .get_isInAsyncPostBack() of the PageRequestManager to prevent a user from being able to access another part of the page until the async postback is complete.
Another part of this page needs to dynamically update multiple update panels consecutively. Since the update panels use async triggers, calling __doPostBack("<%=ButtonName.ClientID %>", 'PanelId'); fires asynchonously. Because of this, it will quickly move along to the next iteration of the loop and try to update the next panel. However, the second iteration fails because there is already another update panel doing an async postback.
Ideally, there would be a way to wait until .get_isInAsyncPostBack() returns false without blocking other client activity.
Research has lead me to a lot people with my problem, almost all of whom are advised to use setTimeOut(). I do not thing this will work for me. I don't want to wait for a specified amount of time before executing a function. I simply want my Javascript to wait while another script is running, preferably wait until a specific condition is true.
I understand that many will probably want to suggest that I rethink my model. It's actually not my model, but one that was handed to our development team that is currently a total mess under the hood. Due to time contraints, rewriting the model is not an option. The only option is to make this work. I think that if I had a way to make the client code wait without blocking, my problem would be solved.
There is no such functionality such as wait or sleep in javascript, since it would stop browser from responding.
In your case I would go with something similar to following:
function wait(){
if (!condition){
setTimeout(wait,100);
} else {
// CODE GOES IN HERE
}
}
It's easy to make a mistake when calling setTimeout that will cause the JavaScript call stack to fill up. If your function has parameters, you need to pass those in at the end of the setTimeout parameter list like this:
function wait(param1, param2){
if (!condition){
setTimeout(wait, 100, param1, param2);
} else {
// CODE GOES IN HERE
}
}
If you pass parameters or even include empty () after the name of the function, it will be executed immediately and fill up the stack.
// This is the wrong way to do it!
function wait(param1, param2){
if (!condition){
setTimeout(wait(param1, param2), 100); // you'll get max call stack error if you do this!
} else {
// CODE GOES IN HERE
}
}
I needed to slow down a process and came up with a helpful little method.
const wait = (seconds) =>
new Promise(resolve =>
setTimeout(() => resolve(true), seconds * 1000)
);
And you can use it like this.
const doWork = async() => {
// After 3 seconds do something...
await wait(3);
console.log('work done');
}
This function calls condFunc which should return true when condition is met. When that happens readyFunc is called. checkInterval sets checking rate in milliseconds
var wait = function(condFunc, readyFunc, checkInterval) {
var checkFunc = function() {
if(condFunc()) {
readyFunc();
}
else
{
setTimeout(checkFunc, checkInterval);
}
};
checkFunc();
};
Usage:
wait(
function() { return new Date().getSeconds() == 10; },
function() { console.log("Done"); },
100
);
prints "Done" when current time is 10 seconds after minute

How to write a node.js function that waits for an event to fire before 'returning'?

I have a node application that is not a web application - it completes a series of asynchronous tasks before returning 1. Immediately before returning, the results of the program are printed to the console.
How do I make sure all the asynchronous work is completed before returning? I was able to achieve something similar to this in a web application by making sure all tasks we completed before calling res.end(), but I haven't any equivalent for a final 'event' to call before letting a script return.
See below for my (broken) function currently, attempting to wait until callStack is empty. I just discovered that this is a kind of nonsensical approach because node waits for processHub to complete before entering any of the asynchronous functions called in processObjWithRef.
function processHub(hubFileContents){
var callStack = [];
var myNewObj = {};
processObjWithRef(samplePayload, myNewObj, callStack);
while(callStack.length>0){
//do nothing
}
return 1
}
Note: I have tried many times previously to achieve this kind of behavior with libraries like async (see my related question at How can I make this call to request in nodejs synchronous?) so please take the answer and comments there into account before suggesting any answers based on 'just use asynch'.
You cannot wait for an asynchronous event before returning--that's the definition of asynchronous! Trying to force Node into this programming style will only cause you pain. A naive example would be to check periodically to see if callstack is empty.
var callstack = [...];
function processHub(contents) {
doSomethingAsync(..., callstack);
}
// check every second to see if callstack is empty
var interval = setInterval(function() {
if (callstack.length == 0) {
clearInterval(interval);
doSomething()
}
}, 1000);
Instead, the usual way to do async stuff in Node is to implement a callback to your function.
function processHub(hubFileContents, callback){
var callStack = [];
var myNewObj = {};
processObjWithRef(samplePayload, myNewObj, callStack, function() {
if (callStack.length == 0) {
callback(some_results);
}
});
}
If you really want to return something, check out promises; they are guaranteed to emit an event either immediately or at some point in the future when they are resolved.
function processHub(hubFileContents){
var callStack = [];
var myNewObj = {};
var promise = new Promise();
// assuming processObjWithRef takes a callback
processObjWithRef(samplePayload, myNewObj, callStack, function() {
if (callStack.length == 0) {
promise.resolve(some_results);
}
});
return promise;
}
processHubPromise = processHub(...);
processHubPromise.then(function(result) {
// do something with 'result' when complete
});
The problem is with your design of the function. You want to return a synchronous result from a list of tasks that are executed asynchronously.
You should implement your function with an extra parameter that will be the callback where you would put the result (in this case, 1) for some consumer to do something with it.
Also you need to have a callback parameter in your inner function, otherwise you won't know when it ends. If this last thing is not possible, then you should do some kind of polling (using setInterval perhaps) to test when the callStack array is populated.
Remember, in Javascript you should never ever do a busy wait. That will lock your program entirely as it runs on a single process.
deasync is desinged to address your problem exactly. Just replace
while(callStack.length>0){
//do nothing
}
with
require('deasync').loopWhile(function(){return callStack.length>0;});
The problem is that node.js is single-threaded, which means that if one function runs, nothing else runs (event-loop) until that function has returned. So you can not block a function to make it return after async stuff is done.
You could, for example, set up a counter variable that counts started async tasks and decrement that counter using a callback function (that gets called after the task has finished) from your async code.
Node.js runs on A SINGLE threaded event loop and leverages asynchronous calls for doing various things, like I/O operations.
if you need to wait for a number of asynchronous operations to finish before executing additional code
you can try using Async -
Node.js Async Tutorial
You'll need to start designing and thinking asynchronously, which can take a little while to get used to at first. This is a simple example of how you would tackle something like "returning" after a function call.
function doStuff(param, cb) {
//do something
var newData = param;
//"return"
cb(newData);
}
doStuff({some:data}, function(myNewData) {
//you're done with doStuff in here
});
There's also a lot of helpful utility functions in the async library available on npm.

Infinite loop triggered by absence of alert()

For reasons entirely beyond my comprehension, this function runs just fine:
function foo() {
var loop = true;
var abc = ["a","b","c"];
var ctr = 0;
while(loop) {
$("<img />").error(function () {
loop = false;
}).attr('src','images/letters/'+abc[1]+(ctr++)+".jpg");
alert(ctr);
}
}
But moving the alert(ctr) outside the while triggers an infinite loop.
function foo2() {
var loop = true;
var abc = ["a","b","c"];
var ctr = 0;
while(loop) {
$("<img />").error(function () {
loop = false;
}).attr('src','images/letters/'+abc[1]+(ctr++)+".jpg");
}
alert(ctr);
}
Can anyone help clarify?
I would be mighty wary of doing what you are doing. You see, you are essentially spinning off an infinite loop, relying on an error event thrown by JS to interrupt that loop. I imagine you are seeing the above behavior because calling alert() is pumping messages, and giving a chance for the event to fire. In the latter example, you are just spinning the CPU, not giving anything else a chance to happen.
In your first snippet, the alert function call inside the loop causes to stop it temporarily, presumably giving time to the error callback to execute, setting the loop flag to false.
In your second snippet, when the alert call is not present within the while, the loop will execute many times, firing the browser's long-running script warning.
Javascript is single threaded and synchronic. If you remove the alert your loop will keep it busy and the error will not be thrown (it will be queued, actually) until the processing finishes. The alert makes your infinite loop pause for a while and lets Javascript process the queued events.
Can't see why, but seems like in the 2nd case there is a mixup of variable scope for some reason.
In most browsers, nothing will be written to the page until either the user is explicitly given control (in your case via an alert) or the javascript reaches it natural conclusion. the .error() is never made without the alert to pause the loop.
Would it be possible to write a for loop given the length of abc?

Categories

Resources