File APIs Javascript FileReader onload - javascript

I am using File APIs with Javascript.
I need to wait for the completation of onload method, how can I do it?
reader.onload = function (e) {
contents = reader.result;
var addAttchCallBack = loadRequestExecutor();
addAttchCallBack.done(function (data) {
alert("ok");
})
};
alert("Ko");
I see always before "Ko"
N.B: the function loadRequestExecutor() correctly returns a promise obj.
Thanks,Nk

You really need to study up on Async behavior and callbacks, then take on understanding promises, as your examples are an odd combination of callbacks and promises, but, to try and explain what is going on in basic terms:
Example 1:
You always seeing KO first, because the first example does this:
Assign a function to a property that will be called back later
Show a KO alert
At some time later the file loads, starts the executor, which on complete (if it ever does) alerts OK
so, basically your onload function will only get called after the file loads (asynchronously), so the alert on the next line gets executed immediately.
Example 2:
You second example, in a comment, is this:
$.when(reader.onload = function (e) {
contents = reader.result;
return loadRequestExecutor();
}).done(function (a) {
alert("ok");
});
alert("KO");
Which translates to:
Assign a function to a property that will be called back later
Pass that same function to when but do not execute it!!!
Show a KO alert
At some time later when the file loads, return the loadRequestExecutor() to the filereader!!!
The end result is not returning the promise to the wait, which is what you probably meant, so it will never work as expected.
Suggestion:
I do not know the plugins that well, but you appear to need to record a promise relating to the load request executor, if that is what you want to wait for.
// Create the loadRequestExecutor and record the promise
var addAttchCallBack = loadRequestExecutor();
// Setup the onload callback
reader.onload = function (e) {
contents = reader.result;
alert("ok - file load is done");
};
// Listen for the loadRequestExecutor to complete
addAttchCallBack.done(function (data) {
alert("Ko - loadRequestExecutor is done");
})
alert("I am just an alert that will happen first, as everything above is asynchronous!");
Your overall aim is not clear from the question, so this answer mainly focuses on exampling why your two attempts do not work as you expected.

Related

Perform operation after all the call back functions got executed

I have the following scenerio
asyncFunction(x1)
asyncFunction(x2)
asyncFunction(x3)
...
...
asyncFunction(xn)
The function of the asyncFunction is to get data and image from the server and append to the body of the html. The problem is the data sizes vary each time so each function may complete at different time. This makes it useless as some top elements would be still loading even after the bottom elements are loaded.
How can I write the Javascript code in such a way that the functions data is appended after all the callbacks have been completed or alternatively execute the function i only after function j has been executed, where j < i.
I am using Javascript and Ajax for getting the data.
PS: This is almost similar to a news feed.
You can use jquery deffered objects
In every function define deffered object, for example:
var asyncFunction1 = function(x1) {
var d = new $.Deferred();
...
//when it will be ready
d.resolve();
...
return d.promise();
}
And then
$.when(asyncFunction1(), asyncFunction2(), ...).done(function() {
// here all functions will be finished
});
Use can do this easily with using promises. Inform yourself about the topic with articles like this. Then I would suggest you have a look at the Q framework.
What you are looking for would then be that you want to execute code only after all promises have been resolved. This would look like this if you use Q:
Q.all([a,b,c,d]).then(function(){
//runs after all of the promises fulfilled
});

$.when not working as I would expect

Please see the JavaScript below:
function LoadAjax(){
$.when(Possibles()) //Display Possibles first
.done(function () {
//alert('Possibles complete);
GetSQLTable();
LinkedUSNs();
})
}
I expect Possibles to complete and all the information to appear on the webpage before GetSQLTable and LinkedUSNs start. However, this does not happen. The information from GetSQLTable appears first. However, if I add an alert box (currently commented out in the code above), then it works. Why is this?
Possibles(), GetSQLTable() and LinkedUSNs() return HTML tables to the webpage via AJAX (JQuery).
Since you haven't posted the entire code. You might want to check the current state of the Deferred object in your promise (Possibles() function):
$.Deferred(function(deferred) {
// debug
console.log(deferred.state());
});
Or you can call resolved in your promise (which would call any doneCallbacks added by deferred.then() or deferred.done()):
$.Deferred(function(deferred) {
// dom ready?
$(deferred.resolve);
});

How to get value from resolved jQuery.Deferred()?

Here is my basic situation:
function somePostThing() {
return $post("/someUrl").done(doSomething);
}
function doSomething(data) {
// do stuff with the data
}
var object = {};
object.deferred = somePostThing();
// A few cycles later, object.deferred may be resolved or unresolved
object.deferred.done(function () { /* ... */ });
The last line may or may not work, because done won't fire in the event that the deferred object is already resolved. I would like to be able to do something like this:
function doSomethingWithData(data) {
// do stuff
}
var value;
if (object.deferred.isResolved()) doSomethingWithData(object.deferred.value());
else object.deferred.done(doSomethingWithData);
How do I get the value of an already resolved jQuery.Deferred()?
No, that's actually exactly why the whole "Deferred" mechanism came into being. If you pass in a "done" function after the asynchronous process has been resolved, it most definitely will be executed immediately.
From the jQuery API docs:
If more functions are added by deferred.then() after the Deferred is resolved, they are called immediately with the arguments previously provided.
That's true for the ".done()" functions also.
JavaScript in a browser is single threaded. So, in the following code snippet:
object.deferred = somePostThing();
// Nothing can happen to object.deferred here
object.deferred.done(function () { /* ... */ });
nothing will happen in between the first line and the last line. "A few cycles later" doesn't mean anything in JavaScript-land. Something will only happen to object.deferred after the function that is executing returns.

How to add a callback to a function in javascript

I have two javascript functions
function one () {
do something long... like writing jpgfile on disk
}
function two () {
do something fast... like show the file
}
I call it (in jQuery) like this
one ();
two ();
Because function two needs the link file from function one, i need to be sure the execution is completed... so getting the function two in the callback of function one should be the trick.. but how to do that ?
note : I did put an alert ('aaa') between those two functions to let function one complete, and it worked fine... when the alert is commented (removed) nothing works anymore !
You only need to use a callback if you are doing something asynchronous, otherwise it doesn't matter how long something takes, the next function won't run until the first has finished.
A callback is just passing a function as an argument, and then calling it when done.
function one (callback) {
do something long... like writing jpgfile on disk
callback();
}
function two () {
do something fast... like show the file
}
one(two);
Obviously, if you are doing something asynchronous, then you need something that will tell you when it is finished (such as an event firing).
Simple:
function one (callback) {
do something long... like writing jpgfile on disk
if(callback) callback();
}
function two () {
do something fast... like show the file
}
one(two);
Try this,
$.when($.ajax(fuction1())).then(function () {
fuction2;
});
Here fuction1 is your first function to call, and fuction2 is your second function.
I think it's easy if the browser wait for the process inside "one()" to be done before execute the next line of command. The iceberg hit titanic cause it doesn't wait. Then executing this:
one(two) // while two is the callBack parameter
is nothing different from:
one()
two()
I suggest using a setInterval.
function one(){
//--- Write the file to disk
//.....................
}
function runTwo(){
if (check_the_written_file_existence){
clearInterval(t)
two();
}
}
var t = setInterval("runTwo()",500)
The most important point is that if there's an event fires when the "long process" in function "one()" has done, you just need to bind function two to that event. Unless, you must check the result by someway every span of time until it's really done.

AJAX workflow: How do I order the execution of these functions?

I'm trying to figure the best way to get my functions executing in the correct order.
I have 3 functions
function 1 - squirts OPTIONs into a SELECT via JSON and marks them as selected
function 2 - squirts OPTIONS into a 2nd SELECT and marks them as selected
function 3 - gets the values from the above SELECTs along with some additional INPUT values, does an AJAX GET resulting in JSON data, which is read and populates a table.
With JQuery Onload, I execute:
function1();
function2();
function3();
I'm finding function3 is executing before the SELECTs have been populated with OPTIONS and hence the table has no results, because the values sent in the GET were blank.
I know this is probably a very simple problem and that there are probably a dozen ways to accomplish this, but basically I need the best way to code this so that function3 only runs if function1 and 2 are complete.
I've come into Javascript via the back door having learnt the basics of JQuery first!
Thanks for your assistance.
Javascript executes synchronously, which means that function3 must wait for function2 to complete, which must wait for function1 to complete before executing.
The exception is when you run code that is asynchronous, like a setTimeout, setInterval or an asynchronous AJAX request.
Any subsequent code that relies on the completion of such asynchronous code needs to be called in such a manner that it doesn't execute until the asynchronous code has completed.
In the case of the setTimeout, you could just place the next function call at the end of the function you're passing to the setTimeout.
In the case of an AJAX call, you can place the next function call in a callback that fires upon a completed request.
If you don't want the execution of the subsequent function to occur every time, you can modify your functions to accept a function argument that gets called at the end of the asynchronous code.
Something like:
function function1( fn ) {
setTimeout(function() {
// your code
// Call the function parameter if it exists
if( fn ) {
fn();
}
}, 200);
}
function function2() {
// some code that must wait for function1
}
onload:
// Call function1 and pass function2 as an argument
function1( function2 );
// ...or call function1 without the argument
function1();
// ...or call function2 independently of function1
function2();
I recommend you use a Promises library. You can hack simple solutions like other answers suggest, but as your application grows, you'll find you are doing more and more of these hacks. Promises are intended to solve these kinds of problems when dealing with asynchronous calls.
The CommonJS project has several Promises proposals which you should check out. Here is a question I asked on SO about Promises a while back with links to other solutions. Learn more about Promises in this Douglas Crockford video. The whole video is good, but skip to just past half way for promises.
I'm using the FuturesJS library currently as it suits my needs. But there are advantages to other implementations as well. It allows you to do sequences very easily:
// Initialize Application
Futures.sequence(function (next) {
// First load the UI description document
loadUI(next); // next() is called inside loadUI
})
.then(function(next) {
// Then load all templates specified in the description
loadTemplates(next); // next() is called inside loadTemplates
})
.then(function(next) {
// Then initialize all templates specified in the description
initTemplates();
});
Even more powerful is when you need to join async events together and do another action when all of the other async events have completed. Here's an example (untested) that will load a bunch of HTML files and then perform an action only once ALL of them have completed loading:
var path = "/templates/",
templates = ["one.html","two.html","three.html"],
promises = [];
$.each(templates, function(i,name) {
promises[i] = Futures.promise();
var $container = $("<div>");
$container.load(path+name, function(response,status,xhr) {
promises[i].fullfill();
}
});
Futures.join(promises, {timeout: 10000}) // Fail if promises not completed in 10 seconds
.when(function(p_arr) {
console.log("All templates loaded");
})
.fail(function(p_arr) {
console.log("Error loading templates");
});
This might be overkill for your application. But if the application is growing in complexity, using promises will help you in the long run.
I hope this helps!
invoke function2 inside of function1 and function3 inside of function2.
It's not clear why f1 and f2 are executing before f3.
Also, are you using the preferred $(document).ready() or some variation of onload?
It might be helpful if you provide a reproducible test case.
fun3() will only run after both are ready. It might run twice. You can fix this with a lock inside fun3() you would need a Singleton to guarantee it works correctly.
var select1ready = false, select2ready = false;
fun1()
{
// do stuff
select1ready = true;
fun3();
}
fun2()
{
// do stuff
select2ready = true;
fun3();
}
fun3()
{
if (select1ready && select2ready)
{
}
}
fun1();
fun2();

Categories

Resources