at the beginning of my html iam initializing variable "movieSRC" like this:
<script type="text/javascript">
var activeStep = getUrlVars();
var movieSRC;
cloud.getStepsForModules(activeStep.module, "UMCK").then(function(steps) {
var calculatedStep = activeStep.step - 1;
movieSRC = steps.steps[calculatedStep].movie;
});
at the end of my html i have some function for videojs.
<script type="text/javascript">
_V_("movie").ready(function() {
var myPlayer = this;
myPlayer.src(movieSRC);
</script>
</html>
I dont understand why a html part at the end will be loaded first and a one after the other at the beginning of my page as a second one. i need it opposite!
i need to keep videojs script at the end of the page because with video should be loaded first and just after that a script.
conclusion: movieSRC in myPlayer.src(movieSRC) is alwas empty :(, but why?
It is executing in order. First a couple of variables are declared, then a function is executed, then later that part at the end executes. What you're overlooking is that the function being executed is asynchronous. And no matter how fast it runs, it's highly unlikely that it will complete before the page finishes loading.
This is asynchronous:
cloud.getStepsForModules(activeStep.module, "UMCK")
So while it's executing everything else is loading. Anything that you need to happen after it executes will need to be invoked from its .then() handler:
cloud.getStepsForModules(activeStep.module, "UMCK").then(function(steps) {
var calculatedStep = activeStep.step - 1;
movieSRC = steps.steps[calculatedStep].movie;
// I don't know this plugin, but find your "myPlayer" here somehow
myPlayer.src(movieSRC);
});
Or perhaps this order will make more sense overall for the plugin:
_V_("movie").ready(function() {
var myPlayer = this;
cloud.getStepsForModules(activeStep.module, "UMCK").then(function(steps) {
var calculatedStep = activeStep.step - 1;
movieSRC = steps.steps[calculatedStep].movie;
myPlayer.src(movieSRC);
});
});
Most likely, the script at the end is being evaluated before the response returns from the cloud.getStepsForModules function above.
Also, there's a syntax error in the second script - you're missing the closing brace/paren/semicolon set.
Try putting the function that uses the result in the callback, like
<script type="text/javascript">
var activeStep = getUrlVars();
var movieSRC;
cloud.getStepsForModules(activeStep.module, "UMCK").then(function(steps) {
var calculatedStep = activeStep.step - 1;
movieSRC = steps.steps[calculatedStep].movie;
_V_("movie").ready(function() {
var myPlayer = this;
myPlayer.src(movieSRC);
});
});
JavaScript code does execute in the order it appears. However, there are functions that are asynchronous, which means they execute in a separate thread. Is it possible that your first function is asynchronous?
If you want to make sure that certain code is executed AFTER an asynchronous function, call that code in the asynchronous function's callback method.
Related
Please bear with me since I am a newbie in JS programming.
I have the following problem:
One of my modules contains a setInterval loop.
This module is called by my server.js when an HTML button is clicked (ON, variable state in the code). I would like to interrupt its execution (OFF) from the server.js but it doesn't work..
I know it feels like a duplicate question, but I have searched a lot for the info inside Stack Overflow and all questions refer to code being executed and stopped from within the same file. In my case, I am calling a method in an external file (which contains the setInterval) and I want to trigger clearInterval which should be ran in that external file!
Simplified code below:
action.js
module.a = function(milisec) {
var myVar = setInterval( function() { do stuff }, milisec);
}
module.exports = methods;
My first attempt:
Server.js
// var state is a button on my HTML
var actions = require('./actions');
If (state == 1)
{ actions.a(milisec) }
If (state == 0)
{ clearInterval(myVar) }
But it didn't work. And I think it's also clear why: The code has no clue where I got the myVar from, basically I think I should call a function from inside the module to stop the setInterval, therefore, I included the function stop() in the method.
My second attempt:
action.js
methods.a = fuction(milisec) {
var myVar = setInterval( function() {
console.log("I'm being executed");}, milisec);
function stop() {
clearInterval(myVar);
}
}
Module.exports = methods;
But I don't know how to refer to the function inside my methods.a on the server.js file
I've tried:
actions.a.stop()
but it doesn't work at all..
Is it even possible? Is there a way to execute the clearInterval in my server.js?
Appreciate your help
You are declaring myVar inside of methods.a(), making it's scope local to that function. Try declaring myVar outside of the function.
function getArray() {
var j = document.createElement('script');
j.src = "http://code.jquery.com/jquery-2.1.4.min.js";
var head = document.getElementsByTagName('head')[0];
head.appendChild(j);
var my_array = [];
j.addEventListener('load',function(){
// Some jQuery codes to fill my_array
});
return my_array;
}
I use above code to dynamically load jQuery in console, and then use jQuery to get some data from the DOM and store them in the array. However, it returns an empty array. I think it is because loading jQuery takes some time and the function gets returned before the jQuery is loaded and the jQuery codes are executed.
So before getArray() returns, I must make sure the jQuery codes have been executed. I've tried to put return my_array inside the addEventListener, of course it won't work because that way it will return the anonymous function. I can think of some ways to deal with this issue, like making the my_array a global so I don't have to return the function, or putting the jQuery loading codes to another loadjQuery function and call it before I execute the jQuery codes, but is there a better way to do it?
The problem is due to asynchronous call of loading jquery script.
The best way to do it will be, write a function to load a script and pass the callback function, then on successful load of script call your callback function, eg:
function loadScript(callback) {
var j = document.createElement('script');
j.src = "http://code.jquery.com/jquery-2.1.4.min.js";
var head = document.getElementsByTagName('head')[0];
head.appendChild(j);
j.addEventListener('load',function(){
if(typeof(callback) == "function")
});
}
function getArray(){
var my_array = [];
// Some jQuery codes to fill my_array
return my_array;
}
loadScript(getArray)
Unfortunately, that can't be done. JavaScript is an event based single-thread asynchronous language. What you're trying to do can't work in that type of environment.
However, it's likely you simply need to load jQuery before processing this function (even using a simple <script> tag) to solve your issue. Otherwise, you're likely to encounter a very noticeable delay when calling the function due to the downloading & evaluating of the jQuery library. Another issue would be that if you call the function more then 1 time, you'll load jQuery again, and that might create a big big mess.
Alternatively, if you "insist" on using jQuery & have it only loaded once your function is called, you could return a Promise that will resolve to your array like this (This will require a supporting browser or some polyfills / promise library):
function getArray() {
var j = document.createElement('script');
j.src = "http://code.jquery.com/jquery-2.1.4.min.js";
var head = document.getElementsByTagName('head')[0];
head.appendChild(j);
return new Promise(function(resolve, reject) {
j.addEventListener('load',function(){
var my_array = [];
// Some jQuery codes to fill my_array
resolve(my_array);
});
});
}
Suppose I load these scripts from my host webpage :
<script src="http://www.mywebsite.com/widget/widget.js?type=normal" type="text/javascript"></script>
<script src="http://www.mywebsite.com/widget/widget.js?type=rotation" type="text/javascript"></script>
and I'd like to execute the second one only when the first one have finished (totally; it can contain asynch functions).
How can I do it?
You're already doing it right : the scripts are executed in the order of integration in the page, not loading.
EDIT : as MaxArt pointed, this may not be what you're looking for. His answer is a good one.
But generally, you'll want to use javascript usual patterns and event based logic to avoid this kind of problems :
have most of your files define only classes and functions (some of them taking callbacks as parameters)
have a main file launching this and calling the sequence of actions, the asynchronicity being handled via callbacks.
My main code usually looks (a little) like this :
$(window).ready(function() {
var myBigEngine = new BigEngine();
myBigEngine.init(function(){
// do other things, no need to add other layers as user events and ajax message callback will do the rest
});
});
Wrap the whole script in a function, like this:
(function(id) {
var id = setInterval(function() {
if (!window.doneLoading) return;
clearInterval(id);
// The whole script file goes here
...
}, 50);
})();
The setInterval polls the (global, sorry) variable doneLoading. In the first script, you have to set doneLoading to true or any other non-false value when your async function is completely loaded, like at the end of an AJAX request maybe?
Edit: since I'm suggesting to add a global variable to the script, it may as well add a global function. So instead of setting up a setInterval call, wrap the second script inside a function... but like this:
function doneLoading() {
// The whole script file goes here
...
}
In the first script file, at the end of your callback function, just call doneLoading().
Try applying defer="defer" attribute to second <script> declaration like
<script src="http://www.mywebsite.com/widget/widget.js?type=rotation" type="text/javascript" defer="defer" ></script>
you can put second script init function in window.onload event
window.onload = function(){
// call function from second script
}
or with jQuery
$(function(){
// call function from second script
});
you can event add second script with this function
function loadScript(src){
var f=document.createElement('script');
if(f){
f.setAttribute("type","text/javascript");
f.setAttribute("src",src);
document.getElementsByTagName("head")[0].appendChild(f);
}
}
When does JavaScript evaluate a function? Is it on page load or when the function is called?
The reason why I ask is because I have the following code:
function scriptLoaded() {
// one of our scripts finished loading, detect which scripts are available:
var jQuery = window.jQuery;
var maps = window.google && google.maps;
if (maps && !requiresGmaps.called) {
requiresGmaps.called = true;
requiresGmaps();
}
if (jQuery && !requiresJQuery.called) {
requiresJQuery.called = true;
requiresJQuery();
}
if (maps && jQuery && !requiresBothJQueryGmaps.called) {
requiresBothJQueryGmaps.called = true;
requiresBothJQueryGmaps();
}
}
// asynch download of script
function addScript(url) {
var script = document.createElement('script');
script.src = url;
// older IE...
script.onreadystatechange=function () {
if (this.readyState == 'complete') scriptLoaded.call(this);
}
script.onload=scriptLoaded;
document.getElementsByTagName('head')[0].appendChild(script);
}
addScript('http://google.com/gmaps.js');
addScript('http://jquery.com/jquery.js');
// define some function dependecies
function requiresJQuery() { // create JQuery objects }
function requiresGmaps() { // create Google Maps object, etc }
function requiresBothJQueryGmaps() { ... }
What I want to do is perform asynchronous download of my JavaScript and start at the earliest possible time to begin executing those scripts but my code has dependencies on when the scripted have been obviously downloaded and loaded.
When I try the code above, it appears that my browser is still attempting to evaluate code within my require* functions even before those functions have been called. Is this correct? Or am I misunderstanding what's wrong with my code?
Functions are evaluated when called.
For example
function test() {
window.foo = 'bar';
}
console.log(window.foo); // => undefined
test();
console.log(window.foo); // => bar
Even though test was created before the first console.log, window.foo is not populated until test is actually called.
If your requires* functions are hanging/blocking, then you need to show the code for those (why would you not provide the source for the problematic ones?)
Edit:
Currently, your site is blanking out on me when you attach the loaded <script> to the <head>.
Anyway, a quick fix would be to place the scripts you wants near the bottom of the page, before </body>, because only scripts in <head> will fully block the page while loading.
There are some elegant ways to late-load resources, but, to keep it simple ..
<script type="text/javascript" src="http://path/to/jquery.js"></script>
<script type="text/javascript">
requiresJQuery(); // jQuery is available at this point
</script>
</body>
The point is that, since the <script> is placed AFTER your main elements, the DOM elements will be available (and potentially loaded) before the browser starts to download your other libraries.
Yes, you are probably misunderstanding. Even if your functions contain a syntax error, it should not matter until you actually call the function.
Could it be that you're calling those functions from somewhere else? Maybe you didn't provide accurate code samples?
i have this block of code:
$(document).ready(function() {
//<![CDATA[
var who;
FB_RequireFeatures(["Api"], function(){
var who = api.get_session().uid;
alert(who);
});
alert("the uid is: "+who);
//]]>
});
the problem:
the code outside the FB_RequireFeatures block is executing before the one inside it.
due to which the value of who is coming out to be undefined.
what am i doing wrong?
The FB_RequireFeatures function appears to be making an asynchronous call, so you're not doing anything wrong, that's just the way it works - the alert is called before the request comes back.
You must design your code in a way that the code that depends on the result of the FB_RequireFeatures functions are called only after the request completes. You can call another function inside the callback, for example:
var who;
$(document).ready(function() {
FB_RequireFeatures(["Api"], function() {
who = api.get_session().uid;
doSomeOtherStuff();
});
});
function doSomeOtherStuff() {
alert("the uid is: " + who);
}
Now the doSomeOtherStuff function is called only after the FB_RequireFeatures function finishes, and you should do all following code inside the doSomeOtherStuff function – which you can name to be anything you want, obviously.
I moved the who variable out of the ready block to keep it in scope for the doSomeOtherStuff function, and removed the var from the inner function so that you're referencing the original variable instead of creating a new one, otherwise it's the same.
You're making a new local who variable. Remove the var from the place where you set who. Also, you can't reference who until the callback to the FB_RequireFeatures function is run.