Is innerHTML asynchronous?
Setting innerHTML is synchronous, as are most changes you can make to the DOM. However, rendering the webpage is a different story.
(Remember, DOM stands for "Document Object Model". It's just a "model", a representation of data. What the user sees on their screen is a picture of how that model should look. So, changing the model doesn't instantaneously change the picture - it take some time to update.)
Running JavaScript and rendering the webpage actually happen separately. To put it simplistically, first all of the JavaScript on the page runs (from the event loop - check out this excellent video for more detail) and then after that the browser renders any changes to the webpage for the user to see. This is why "blocking" is such a big deal - running computationally intensive code prevents the browser from getting past the "run JS" step and into the "render the page" step, causing the page to freeze or stutter.
Chrome's pipeline looks like this:
As you can see, all of the JavaScript happens first. Then the page gets styled, laid out, painted, and composited - the "render". Not all of this pipeline will execute every frame. It depends on what page elements changed, if any, and how they need to be rerendered.
Note: alert()
is also synchronous and executes during the JavaScript step, which is why the alert dialog appears before you see changes to the webpage.
You might now ask "Hold on, what exactly gets run in that 'JavaScript' step in the pipeline? Does all my code run 60 times per second?" The answer is "no", and it goes back to how the JS event loop works. JS code only runs if it's in the stack - from things like event listeners, timeouts, whatever. See previous video (really).
https://developers.google.com/web/fundamentals/performance/rendering/
Getting innerHTML from 3 URLs - Asynchronous Problems
There are two issues:
promise
is a async, so you'll need get your variables within it's callback functionchPageOne
is a string, not element object.
Fixing these issues:
var chNumber = "11885705";
var chPageOne;
var chPageTwo;
var chPageThree;
const urls = [
'https://find-and-update.company-information.service.gov.uk/company/' + chNumber,
'https://find-and-update.company-information.service.gov.uk/company/' + chNumber + '/officers',
'https://find-and-update.company-information.service.gov.uk/company/' + chNumber + '/persons-with-significant-control'
];
// map every url to the promise of the fetch
// let requests = urls.map(url => fetch(url)); //don't need this
// Promise.all waits until all jobs are resolved
Promise.all(urls.map(url => fetch(url)
.then(r => r.text())
.catch(err => console.error(err))))
.then(results => {
// Initialize the DOM parser
var parser = new DOMParser();
// Parse the text
var doc1 = parser.parseFromString(results[0], "text/html");
var doc2 = parser.parseFromString(results[1], "text/html");
var doc3 = parser.parseFromString(results[2], "text/html");
// You can now even select part of that html as you would in the regular DOM
// Example:
chPageOne = doc1.getElementById('content-container');
chPageTwo = doc2.getElementById('content-container');
chPageThree = doc3.getElementById('content-container');
document.getElementById('holdingAreaOne').innerHTML = chPageOne.innerHTML;
document.getElementById('holdingAreaTwo').innerHTML = chPageTwo.innerHTML;
document.getElementById('holdingAreaThree').innerHTML = chPageThree.innerHTML;
var companyName = chPageOne.getElementsByClassName("heading-xlarge")[0].innerText;
console.log(companyName)
//console.log(chPageOne);
//console.log(chPageTwo);
//console.log(chPageThree);
})
.catch(err => console.error(err))
execute .innerHTML in a function
You could try to use setTimeout.
Using a Function
I made this function which makes it easy to supply an array of objects you want to update.
/*
timed_elemet_updates(array, int)
`elements` should be an array of objects which contains the
ID and HTML you want to update.
*/
function timed_element_updates(elements, seconds) {
var element = elements.shift();
document.getElementById(element.id).innerHTML = element.html;
setTimeout(timed_element_updates, (seconds * 1000), elements, seconds);
}
Sample usage:
function start() {
var elements = [
{id: '1a', html: 'bla'},
{id: '2b', html: 'blabla'},
{id: '3c', html: 'blablabla'},
];
timed_element_updates(elements, 1);
}
start();
This answer is more concise (less repeating lines of code), easier to use (just add more elements to the array), and more reusable (no new function for every element)
Original Answer
function one() {
document.getElementById("1a").innerHTML = "bla";
setTimeout(two, 1000);
}
function two() {
document.getElementById("2b").innerHTML = "blabla";
setTimeout(three, 1000);
}
function three() {
document.getElementById("3c").innerHTML = "blablabla";
}
one();
This will call function one()
, then it will call two()
after 1000 milliseconds (1 second), then it will call three()
after 1000 milliseconds (1 second).
Async function and await keyword
Inside js1.js the function execute a promise that is asynchronous and you want it to wait for the Promise's result :
document.getElementById("app3").innerHTML = await myPromise;
At this point, the function will stop and wait for the "myPromise" to complete (resolve or reject).
More on : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Operators/await
The function inside js2.js do not executes code that block it's execution, myDisplay2 can be executed in a synchrone way, the result of the promise will be executed later (if the promise resolve) in the :
.then(function (resp) { document.getElementById("app1").innerHTML = resp; });
To make it short, as soon as you are using "await" the function is "async".
why are ajax asynchronous calls not changing the innerHTML of elements?
You need to set a handler for when the async call completes, and do your DOM updates there:
function change() {
var ajax = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
var changeME = document.getElementById('changeMe');
changeME.innerHTML = ajax.responseText;
}
}
ajax.open('GET', 'data.txt', true);
ajax.send();
}
How to detect when innerHTML is complete
There is no need for such a function. Assigning to innerHTML
will do so immediately before continuing to run any scripts.
If you really need to delay execution (say to allow the browser to redraw), use setTimeout
with a delay of 1
(or other short interval).
Related Topics
Axios Posting Params Not Read by $_Post
When and Where Does JavaScript Run, How About PHP? How to Combine the Two
How to Make JavaScript Object Using a Variable String to Define the Class Name
JavaScript Removeeventlistener Not Working
How to Record Webcam and Audio Using Webrtc and a Server-Based Peer Connection
Image Loaded Event in for Ng-Src in Angularjs
Finding Matches Between Multiple JavaScript Arrays
Upload File with Ajax Xmlhttprequest
Web Workers Without a Separate JavaScript File
Difference Between HTMLcollection, Nodelists, and Arrays of Objects
How to Mock an Es6 Module Import Using Jest
Access Iframe Elements in JavaScript
Fetch Request to Local File Not Working
How Might I Find the Largest Number Contained in a JavaScript Array
Jquery Select Option Click Handler