I would like to know if the initialization flow of AngularJS apps is predictable in terms of the order of execution of different blocks within an HTML document.
I read this question What is meant by Bootstrapping in angular JS?, which explains a lot of the process, but does not answer my question in detail.
I have a plunker example http://plnkr.co/edit/boVFjHWoxdbiADq41dXC?p=preview, where I console.log() numbers, in the order that I thought they would execute. What was a bit surprising though was that the execution of the .run() block seems to be deferred.
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.4.0-rc.0" data-semver="1.4.0-rc.0" src="https://code.angularjs.org/1.4.0-rc.0/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<!--<script src="script.js"></script>-->
<script>
// Code goes here
console.log(1);
angular.module('app', [])
.run(function () {
console.log(2);
setTimeout(function () {
console.log(6);
});
});
</script>
<script>
console.log(3);
</script>
</head>
<body>
<img src="http://www.mrwallpaper.com/wallpapers/Sicily-Italy.jpg" />
<script>
setTimeout(function () {
console.log(5);
})
</script>
<img src="http://www.wishsicily.com/gallery/1370_scicli-ragusa.jpg" />
<script>
console.log(4);
</script>
<h1>Hello Plunker!</h1>
</body>
</html>
So I have a few questions:
Is it safe to say that the run() block, flagged in the console by the number "2", will always be executed after the rest of the page was processed?
I get that what initiates the execution of the .run() block is the call angularInit(), which is executed by the call ready() on DOM ready. Is that correct?
Does that mean that, in effect, the execution of the run() block happens on the same tick, as it would if it was assigned to window.onload?
There is actually documentation about the run block on https://github.com/angular/angular.js/blob/ce669edfa14dc7eb7c389d2f82c9c98399a9009b/docs/content/guide/module.ngdoc
Run Blocks
Run blocks are the closest thing in Angular to the main method. A run
block is the code which needs to run to kickstart the application. It
is executed after all of the service have been configured and the
injector has been created. Run blocks typically contain code which is
hard to unit-test, and for this reason should be declared in isolated
modules, so that they can be ignored in the unit-tests.
The angularInit function initializes the modules which then call their own runblocks. That happens in src/angular.suffix
jqLite(document).ready(function() {
angularInit(document, bootstrap);
});
So the run function will always be called after the document loaded.
Since Angular will start initializing then, there may be some time between the window.load and the initializing.
Related
I've got two javascript files, screenfunction.js and map.js
In screenfunctions.js there's a function that I want to be able to start another function called "go" which is in map.js, is this possible?
This is what's written in the function in screenfunctions.js. The console obviously tells me that "go" is not defined.
if (doAnimation == 0){
go(function(){});
}
Yes, as long as the required function has already been included beforehand.
There are two ways to do this.
ECMAScript modules
Read more about ES modules on the MDN.
Use this if you are writing a server-side application with Node.js (in which case ignore index.html), or writing a client-side application for modern browsers. All major browsers have supported ES modules since ~2018, but IE does not support them (check Can I use here).
<!-- index.html -->
<html>
<head>
<!-- ... -->
<script type="module" src="./screenfunctions.js"></script>
<script type="module" src="./map.js"></script>
</head>
<!-- ... -->
</html>
// screenfunctions.js
export function go() {
console.log('Called go()');
// ...
}
// map.js
import { go } from './screenfunctions.js';
go();
Legacy global declaration
Use this if you are writing a client-side application which must work in older browsers. This approach is worse because the function is declared in the global scope. This could interfere with other code which is also included. This approach is also more prone to breaking because the dependency of the second script upon the first is not obvious at first glance.
<!-- index.html -->
<html>
<head>
<!-- ... -->
<script src="./screenfunctions.js"></script>
<script src="./map.js"></script>
</head>
<!-- ... -->
</html>
// screenfunctions.js
function go() {
console.log('Called go()');
// ...
}
// map.js
// `go()` already exists, because `./screenfunctions.js` was included earlier in the markup.
go();
Yes! You'll want to export the function you want to use. See this doc for more information and examples.
It is well known to everyone that using defer is an efficient way to minimize the loading time of a website.
In my project, I am using Vue (included in the header using defer) and in a circumstance, I want to use a component that is created by another person. When I try to do Vue.Component(...) in the body of the HTML, it says Vue is undefined. It seems that my script in the body is running before the external script has been loaded. Is there any way to fix this issue?
I tried to do document.onload, but the function itself is not working.
PS: Just to be clear, the external script is referring to my js file where Vue is defined and I am not talking about the third party library at all.
Instead of document.onload you need to use window.onload or document.body.onload.
But an even better way is to wait for the load event on <script> tag:
<html>
<head>
<script id="vue-script" src="vue.js" charset="utf-8" defer></script>
</head>
<body>
<script type="text/javascript">
function onVueLoaded() {
Vue.render();
}
if ('Vue' in window) {
onVueLoaded();
} else {
var script = document.getElementById('vue-script');
script.addEventListener('load', onVueLoaded);
script.addEventListener('error', () => console.warn('failed to load Vue.js'));
}
</script>
</body>
</html>
Here I also added a handler for the error event if you wanted to explicitly handle loading errors.
Tell me if I am wrong. The JavaScript code execute as a single thread.
The execution of below JavaScript code will be A,B and C, sequentially right.
<script src="A"> .... </script>
<script src="B"> .... </script>
<script src="C"> .... </script>
The execution of below code will depend upon the code and the time given to each scripts means first 'A' will start to execute (or 'B', don't know), the execution of 'A' will stop because the time given to it is complete than the others will get the same chance say 'B' , than 'C' and than 'A' again resume and the cycle goes on till the execution of each scripts done.
<script async src="A"> .... </script>
<script async src="B"> .... </script>
<script async src="C"> .... </script>
But what happen when there are both synchronous and asynchronous scripts occur like below.
<script sync src="A"> .... </script>
<script async src="B"> .... </script>
<script sync src="C"> .... </script>
<script sync src="D"> .... </script>
<script async src="E"> .... </script>
The async attribute merely means that the script will be downloaded sometime later and therefore will start executing sometime later. <script> tags without that attribute will be downloaded immediately and block the rest of the page until the download and execution is finished.
async does not mean that once the script runs, it may get interrupted at any time and another script may start to run. That is cooperative multitasking/CPU scheduling and is absolutely not what happens here. The first async script which happens to complete downloading will run, until it is done, at which point the next script will start to run if there's any.
So, yes, with async you do not know when your script will start executing, but once it does, it is the only thing running until it relinquishes that power (meaning the script and/or function exits).
I haven't seen anywhere the sync attribute that we can use. As far as I know there's only the way we can use the attribute is async.
But for your query, you should be using without attribute and this will be synchronous automatically:
<script src="A"> .... </script>
<script async src="B"> .... </script>
<script src="C"> .... </script>
<script src="D"> .... </script>
<script async src="E"> .... </script>
And now to answer your question,
Asynchronous scripts are loaded in the background while synchronous scripts are loaded in order and affect html and css also.
So, we can not guarantee that using like your exammple order of scripts with synchronous and asynchronous scripts because asynchronous scripts loaded in the background and may be loaded before or after the other synchronous scripts.
I theoretically know the differences between async and defer used in <script> tag.
async: The script is executed asynchronously with the rest of the page (the script will be executed while the page continues the parsing).
defer: The script is executed when the page has finished parsing.
But can't understand the mechanism they follow.
I have the following 2 files-1.js and 1.html.
1.js
alert('Running external JS');
1.html
<html>
<body>
<script src="1.js" async></script>
<script>
for(var i=0;i<5;i++)
{
alert('HTML code1');
}
</script>
<script>
for(var i=0;i<5;i++)
{
alert('HTML code2');
}
</script>
</body>
</html>
The html file executes s.t. all the alert statements execute first and then at last the script 1.js executes i.e. it acts similarly as when I use defer in place of async in the <script>-tag.
As per my expectation as the external script is much smaller than the code in the HTML itself it should have been triggered anywhere in between the alert statements in the HTML document as I am using async but acting similar to the effect of using defer.
Please explain what happened here also please correct me if I am wrong.
I am using SharePoint Server 2007 Enterprise with Windows Server 2008 Enterprise. I am developing using VSTS 2008 + C# + .Net 3.5 + ASP.Net. I am learning the following code dealing with javascript, my confusion is for $(function(){...} part of code, when it will be called and what is its function? I did not see any code invokes this function.
<!doctype html>
<html lang="en">
<head>
<title>Test</title>
<link type="text/css" href="tabcontrol/themes/base/ui.all.css" rel="stylesheet" />
<script type="text/javascript" src="tabcontrol/jquery-1.3.2.js"></script>
<script type="text/javascript">
$(function() {
$("#tabs").tabs();
});
</script>
</head>
<body>
<div class="demo">
<div id="tabs">
<ul>
<li>tab1</li>
<li>tab2</li>
</ul>
<div id="tabs-1">
<p>tab1 info</p>
</div>
<div id="tabs-2">
<p>tab2 info</p>
</div>
</div>
</div>
</body>
</html>
thanks in advance,
George
It comes from the jQuery library you're including:
<script type="text/javascript" src="tabcontrol/jquery-1.3.2.js"></script>
$ is an alias for the jQuery function.
See jQuery(callback) reference documentation:
A shorthand for $(document).ready().
Allows you to bind a function to be executed when the DOM document has finished loading. This function behaves just like $(document).ready(), in that it should be used to wrap other $() operations on your page that depend on the DOM being ready to be operated on. While this function is, technically, chainable - there really isn't much use for chaining against it.
For more information, have a look at Tutorials:Introducing $(document).ready()
It will be called when the document is ready. It is equivalent to:
$(document).ready(function() {
...
});
Document.ready indicates that the page is fully loaded on the client. WebParts are serverside controls and will be processed first in order to produce the html document sent to the client. Thus webparts will be processed before the document.ready client-side event fires.
From the Gecko docs:
The load event fires at the end of the document
loading process. At this point, all of
the objects in the document are in the
DOM, and all the images and sub-frames
have finished loading.
$(function(){
});
is jQuery (a Javascript library) shorthand for:
$(document).ready(function(){
});
It is what you use to do with <body onload="xxx"> but more sophisticated. You can get a fuller explanation here.
I'm not sure why you tagged your post "SharePoint" but note that this is not suported on SharePoint pages.
You need to push scripts that run on page load on a stack and SharePoint will execute them. The syntax is:
_spBodyOnLoadFunctionNames.push("myOnloadFunction");
This will require the javascript fu:
function myOnloadFunction()
{
$("#tabs").tabs();
}
to be available, which can execute your onload code.
That's a shorthand used in jQuery and one that is absolutely unclear and unnecessary in my opinion. Not too long ago, we used to write:
$(document).ready(function() {
$("#tabs").tabs();
});
Now we can also write this to do the above:
$(function() {
$("#tabs").tabs();
});
The function that is passed to $(document).ready is executed when the page is loaded and the DOM is ready, in other words the document has been loaded in memory. This code is written in jQuery, a Javascript library that makes DOM operations easier.
This is how the above code translates to plain Javascript:
window.onload = function() {
$("#tabs").tabs();
};
where window is a global object that represents the page window, of course.
This is a jQuery call and it gets called when a document gets loaded.
more info at http://docs.jquery.com/Core/jQuery#callback
That syntax is an alias for
$(document).ready(function(){});
This event is used in jQuery to invoke a script as soon as the DOM is ready. It's like window.onload, but doesn't wait for all the images to fully load before firing.