setTimeout for incremental page load - javascript

Please see the code below:
function GetSQLTable() {
var str = $("#<%=fieldGroupReferences.ClientID%>")[0].value
var res = str.split(",");
$("#LoadingImage").show();
$("#LoadingImage2").show();
for (var i = 0; i < res.length; i++) {
alert(res[i])
(function(i,res) {
setTimeout(function (i,res) {
alert(res[i])
GetSQLTable2(i, res.length,res)
}, 0)
})(i,res)
}
}
The first alert displays the correct information. The second alter errors (undefined). Why is this?
Also, I am informed that this approach should stop the webpage crashing when there are lots of AJAX requests (it is an incremental page load). However, I do not understand how setting a timeout of zero seconds between AJAX requests will help. GetSQLTable2 executes an AJAX call.
fieldGroupReferences can contain up to about 50 values.

This jsbin link should answer your question
JSBIN
When you call
setTimeout(function(res,i){
//using res and i here
},0)
dont use res,i as function parameters,by logic of closure res and i are by default available inside the function. If you use res,i then you are creating a function with new parameters for which values are not being sent to.
So it should just be
setTimeout(function(){
//using res and i here
},0)
I believe when you call setTimeout(function(){},0) the format of setTimeout is something like this,
function setTimeout(callback,time){
after-time{
callback(); //observe here we are not passing anything as arguements, i am not sure but setTimeout may pass its own values like how $.on passes 'events' to callbacks
}
}
To answer your second part as to how setting 0 seconds will help,
by setting 0 seconds, to say in laymans terms you are continuing the flow in an asynchronous manner!!! Hence no matter how many ajax responses are recieved they wont block each other since the code is asynchronously solved

Related

Global variable value not reflecting in loop

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);

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.

Recursion AJAX post, Causing Computer to run slowly

I have this recursion loop where inside the function I have atleast 2 ajax get/post, and the recursion happens after the first ajax get. my function structure is like this,
function Loop() {
$.get(url, data, function(result) {
for loop to render the result {
// render the result here
}
for loop to get another data using the result {
$.post(url, result.data, function(postResult) {
// I don't know what it did here since
// I don't have an access to this post
});
// is there a way here that i will not proceed if the post is not done yet?
}
setTimeout("", 1000); // I wait for 1 second for the post to finish
Loop(); // call the recursion
}, "json");
}
can anyone tell me what's wrong with this code? why do i get a warning from the computer that my script is causing the computer to run slowly. I know that this code is the one causing it, but I don't know the work around.
I know inside the second loop inside the get is causing a lot of memory. Is there a way that it will not loop back if the ajax post is not finished?
Your setTimeout will not neatly pause the code for one second: it will just set a timer for an (empty, in your case) event to go off after a certain time. The rest of the script will continue to execute parallel to that.
So you're currently calling your recursion function a lot more frequently than you think you are. That's your first problem.
Your biggest problem, though, is that regardless of what you're doign in the result of your post, that's in another scope entirely, and you cannot break out of the Loop function from there. There is nothing in your code to break the recursion, so it is infinite, and very fast, and it sends off Ajax requests on top of that.
You need to describe in more detail what you want to achieve, and perhaps somebody can show you how you should do it. The only thing that is certain is that you need to use callbacks. I've written an example but it's making a lot of assumptions. It's a lot of approximations of what I think you might want to achieve, but no doubt you'll need to tweak this a bit to fit your needs. Hopefully it'll give you an idea of the workflow you need to use:
function Loop() {
$.get(url, data, function(result) {
for loop to render the result {
// render the result here
}
// this is what you're looping over in your second loop
var postQueue = result.someArray;
renderChildData(postQueue, 0);
}, "json");
}
function renderChildData(array, index) {
// this is just one item in the loop
var currentItem = array[index];
$.post(url, currentItem, function(postResult) {
// we have received the result for one item
// render it, and proceed to fetch the next item in the list
index++;
if(index < array.length) {
renderChildData(array, index);
}
});
}
First of all this line:
setTimeout("", 1000); // I wait for 1 second for the post to finish
doesn't make your script to wait, since it's improper usage of setTimeout function. I think you should consider to use setInterval instead and do it like:
function Loop() {
$.get(url, data, function(result) {
for loop to render the result {
// render the result here
}
for loop to get another data using the result {
$.post(url, result.data, function(postResult) {
// I don't know what it did here since
// I don't have an access to this post
});
// is there a way here that i will not proceed if the post is not done yet?
}
}, "json");
}
setInterval( Loop, 1000);
This will make execute your function every 1 sec. I guess this is exactly what you wanted to gain. There is no reason to make recursive call here.
it basically happen when you use a huge code on a page ..
so just try to compress this code

Best solution to wait for all ajax callbacks to be executed

Imagine we have to sources to be requested by ajax. I want to perform some actions when all callbacks are triggered. How this can be done besides this approach:
(function($){
var sources = ['http://source1.com', 'http://source2.com'],
guard = 0,
someHandler = function() {
if (guard != sources.length) { return; }
//do some actions
};
for (var idx in sources) {
$.getJSON(sources[idx], function(){ guard++; someHandler(); })
}
})(jQuery)
What I don't like here is that in this case I can't handle response failing (eg. I can't set timeout for response to come) and overall approach (I suppose there should be a way to use more power of functional programming here)
Any ideas?
Regards!
UPD: Thanks for solution with chaining callbacks. I found a good approach here:. this is what was proposed in comments:
(function hidenext(jq){
jq.eq(0).fadeOut("fast", function(){
(jq=jq.slice(1)).length && hidenext(jq);
});
})($('div#bodyContent a'))
With a little bit of tweaking it can wait for the last callback.
Now I want to handle properly long running requests. Any clues?
Duplicate of javascript: execute a bunch of asynchronous method with one callback
function createCallback(limit, fn){
var finishedCalls = 0;
return function(){
if (++finishedCalls == limit){
fn();
}
};
}
var callback = createCallback(4, function(){
alert("woot!");
});
async1(callback);
async2(callback);
async3(callback);
async4(callback);
Maybe you could 'cascade' the downloads, so the callback of the first getJSON triggers download from the next source, and so on? Then in the last callback you have no sources left and can call your 'done' function.
You can always use $.ajax with "async: false" in options and/or use proper callbacks (beforeSend, error, dataFilter, success and complete).
Maybe I am wrong - but the rule is: serialization of AJAX - one at a time
So you HAVE to chain it - each response (call back function) must submit the next one in turn
*.onreadystatechange will give you control (a function that is) )when it is ready - here you can submit the next one in turn

Categories

Resources