Preface:

When combing knowledge points, I found that as one of the mechanisms in browser rendering – asynchronous loading mechanism, when users visit the site, they need to download a variety of resources, such as JS scripts, CSS, pictures, IFrame, etc., it is an essential means to realize the modern website to load pages. There are still many ways to say about the asynchronous loading mechanism, so a knowledge point is singled out for sorting.


In order to understand the asynchronous loading of JAVASCRIPT scripts, it is necessary to understand the two common scenarios in the browser with the effect of page style and JS: blank screen and FOUC (unstylized content flickering).

I. White screen and FOUC

1. Two scenarios that affect the loading order of browser pages

– White screen: a scene in which a page is white when opened and suddenly appears with correct style. Then a piece of white time, is called a white screen. -FOUC (Flash of UnstyledContent) : the UnstyledContent blinks and the network speed is poor. When the page is opened, the style is still displayed, and then the style is sometimes absent, or even when the style is not displayed at the beginning, the style is suddenly restored. (Often found in Firefox)

It is not a bug that resources are loaded and pages rendered differently in different browsers.

2, write a server, verify the blank screen and FOUC effect

In the style file index.html

//index.html <! DOCTYPE html> <html lang="en">
<head>
  <meta charset="UTF-8"> <title>fouc & blank </title> <! <link rel= <link rel="stylesheet" href="b.css? t=10"> / / set the tool, when requesting the file, the server will delay 10 s to load the requested resource, in order to simulate a special slow speeds of the < link rel ="stylesheet" href="a.css? t=3"> </head> <body> <p> Hello </p> <p> -- <script src="A.js? t=5"></script> 
  -->
  <img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/8/15/1653c442f35af77c~tplv-t2oaga2asx-image.image" alt=""> <! -- <link rel="stylesheet" href="c.css? t=6"> -- > <! -- <script src="http://a.jrg.com:8080/B.js?t=4" ></script>  
  <script src="http://b.jrg.com:8080/A.js?t=8" ></script>   -->
  
</body>
</html>
Copy the code

(1) About the white screen, it is necessary to pay attention to the browser for style and JS processing, that is, CSS and JS placement order. Recommendation: Place styles inside and JS below inside.

As shown in the code above, two CSS are introduced in the HTML page: A.css and B.CSS. C.ss (@import”./ c.ss? T = 5 “) ( ), load the CSS style file for 10s. Browsers do this in two ways:

The first: HTML parsing is complete, at this time the CSS file delayed 10 seconds first ignore, first show the content shown in , such as the CSS file after the full load to calculate the style, and then to re-render once

The second kind: even if the HTML DOM tree has been parsed, rendering has been completed, the style that has not been loaded must wait, that is, the CSS style must be fully loaded, acquired, img resource loading is completed, at this time the bottom JS immediately executed, only a one-time display of the page. This method, shown in the example, is the reason for the long blank screen.

(2) Different processing mechanisms of different browsers have different scenarios

A, white screen scene (often appear in Chrome) : open A foreign website, use A foreign server, the font embedded in CSS is Google font, the operation is very slow, wait for A long time suddenly appear page style effect. This is because the page has to wait for the CSS style to complete, or even a 404 load failure, before it is displayed. Then that load time, waiting for a few seconds or so of the white page, is a blank screen

B, Fouc scenario (often found in Firefox) : at the beginning, you will see the style, such as the small style of the word, after the style is loaded, you will see the size of the specified font. For the user, if the same style suddenly goes from small to large, the scene is Fouc (unstyled content flashing).

Summary: No matter CSS styles, or JS files, as long as the extension of the delay, will cause a blank screen

(3) The best placement order of CSS and JS

  • Use the link tag to place the style sheet at the top
  • Put JS at the bottom

Scenario: Assume the top of the JS file page:

  • The JS script blocks the rendering of subsequent content
  • JS scripts block the download of subsequent components such as images
  • If the LOADING time of JS is too long and the CSS needs to wait, a blank screen is displayed for a period of time

Scene description: Introduce a JS file at the top and set a delay time.

Loading order: CSS-js – img – all page display effects are obtained

In this case, img and CSS are loaded concurrently, i.e. two files are loaded simultaneously under the same domain (concurrency is limited). Loading js at the top disables concurrent IMG and CSS and prevents other content from downloading and rendering.

Js does not affect CSS loading, but does affect a calculation of CSS styles. When the JS is loaded, the CSS has been retrieved (but the page is still blank), and the page does not display the effect until the image appears immediately after the JS is retrieved. So js files placed at the top of the page will also result in a blank screen

(3.2) Summary of JS loading characteristics

A, priority to load JS files, js immediately to execute after loading, display the page (CSS style is all loaded, and then display the page once)

Note: CSS is first loaded; If you put it later, other resources will block CSS loading, and it will be too late.

B. Since rendering thread and JS script thread are mutually exclusive, white screen is the reason why rendering process is blocked. When script tag is encountered, js script will be executed first, then render.

  • JS loading time is too late, which leads to a series of problems, such as script will block the rendering of the following content, script will block the download of the following components (mainly refers to img resources download), blank screen, etc.
  • (bottom) can let other loading finish first, JS immediately executed feature can “mop up” the final page effect

C, JS scripts operate on HTML + CSS elements on the page, (when placed at the top) JS is executed first, the elements are not loaded (that is, do not exist), does not appear in the document stream, so it cannot operate the corresponding JS function, at this time the background will report an error.

D, (put top) other JS as a framework language, can form a preliminary framework in advance to effectively constitute the page structure.

Asynchronous loading of JS scripts

1. A question?

The js file that was placed at the top will be loaded early. How can I make it still load later at the top?

2. Solutions:asyncanddefer

(1) What it does: Without defer or async, the browser loads and executes the specified script immediately, before rendering the document element under the

Often used in pages that reference ads and statistics, it does not affect, block, or affect other elements of the page

(2) Async HTML5 adds async attribute to script tag, which is used to load scripts asynchronously: no guarantee of order (independent individual)

<script async src="script.js"</script> /* or */ <scripttype="text/javascript" src="alert.js" async="async"></script>
Copy the code

The browser parses the script tag in the HTML line and finds that it is specified as async, so the parsing execution script is downloaded asynchronously (that is, the loading of subsequent document elements is carried out in parallel with the loading of script.js).

The DOM structure of the page assumes that

(3) Defer

<script defer src="script.js"</script> /* or */ <scripttype="text/javascript" src="alert.js" defer="defer"></script>
Copy the code

When the browser parses to the line

The DOM structure of the page assumes that the script comes before the IMG image, and if your browser supports defer, you will delay downloading the script until the page has loaded. At this point, the DOM already has the IMG element, so the script can easily fetch the IMG SRC and pop the frame.

Summary: The essence of JS is a more flexible loading time and location, so that JS files at the top can be loaded “asynchronously” when necessary elements of the page are loaded, as they are at the bottom.

Three, synchronous and asynchronous

  • Synchronize: Wait for the result
  • Asynchronous: Do not wait for results

Note that asynchrony often accompanies callbacks, but asynchrony is not a callback, and callbacks are not necessarily asynchronous.

// Synchronous sleepfunction sleep(seconds){
    var start = new Date()
    while(new Date() - start < seconds * 1000){
    }
    return} console.log(1) sleep(3)'wake up'Console. log(2) // The order of execution results is: print 1 -- stop 3s -- wake up -- print 2, but in fact, in js environment, it is impossible to stop 3s without doing somethingCopy the code

Synchronous sleep // asynchronous sleepfunction sleep(seconds, fn){
    setTimeout(fn, seconds * 1000)
}
console.log(1)
sleep(3, ()=> console.log('wake up'))
console.log(2)
Copy the code

Draw a picture of synchronous and asynchronous work:

Note, however, that while JS is idle, it is actually a timer in the browser that is working (most likely checking to see if the time is up every once in a while, depending on the Chrome code).

4. Encounter asynchronous instances

1. Asynchrony on the front end: images take time to load

document.getElementsByTagNames('img'[0].width // width is 0 console.log('done')
Copy the code

At first, you get the width directly

<! DOCTYPE html> <html> <head> <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
    <img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/8/17/16546d713fd568f0~tplv-t2oaga2asx-image.image" alt="">
</body>
</html>

var w = document.getElementsByTagNames('img')[0].width
console.log(w)
Copy the code

First draw a schematic diagram:

/ / img before network request information first, empty object var img = document. GetElementsByTagName ('img') [0]Copy the code

Img waits for the network request to complete, and after the complete image information is obtained, an onload event is emitted:

Img If the load is successful, an onload event is triggered to get its width and print out the width img.onload =function(){
     var w =img.width
     console.log(w)
}
Copy the code

✨ Full code:

var img = document.getElementsByTagName('img'[0] // Wait until the network request completes and trigger onload event img.onload =function() {var w = img. Width console. The log (w)} the console. The log (img. Width) / * or * / document in getElementsByTagNames ('img')[0].onload = function(){console.log(this.width) // The width is not 0 console.log(){console.log(this.width)'real done')
}
console.log('done')
Copy the code

Conclusion: Asynchrony wants to get a result, usually by listening for an event, and then telling (the completion time of the event is uncertain, unpredictable), then you can hang a function on onload, waiting for the request to complete, call the onLoad event, which is a callback function.

2. Asynchrony in interview questions

let liList = document.querySelectorAll('li')
for(var i=0; i<liList.length; i++){
    liList[i].onclick = function(){console.log(I)}} // Get all the li elements in the DOM structure, get the length of li to traverse, and print something after each clickCopy the code

The var to let I can crack: zhuanlan.zhihu.com/p/28140450

Let me run the js code above:

var i = 0

[Key points] The variable is raised to:

var i
i =0
Copy the code

So, here’s the code:

let liList = document.querySelectorAll('li'Var I // I is a variable that runs through 6 loops (no more than one)for(i=0; i<liList.length; i++){
    liList[i].onclick = function(){
        console.log(i)
    }
}
Copy the code

Draw a sequence diagram:

If I =5 and I ++ =6, it is not less than liList. Length. If I =5 and I ++ =6, it is not less than liList. After executing the js code, the user starts to operate his mouse. Suppose that after waiting for 3ms, execute Click Li, when you click first (I =0, liList[0], when js has finished executing the code, output I = 6), instead of printing the number when binding the event, that is, the number.

At this point, it is important to know that the following binding events for asynchronous functions are:

XXXX.onclick function(){
        console.log(i)
    }
Copy the code

The browser does not wait for the asynchronous execution, but enters the for loop and prints I =6 before the first click appears. – use the let

Fang Yinghang: It took me two months to understand let

Change var I to let:

let liList = document.querySelectorAll('li')
for(let i=0; i<liList.length; i++){
    liList[i].onclick = function(){
        console.log(i)
    }
}
Copy the code

Run as follows:

Draw a running diagram:

3. Asynchrony in AJAX (must)

// Synchronous Ajaxlet request = $.ajax({
  url: '. '// get the current url async:false}} console.log(request.responsetext) prints out the responseText of the request (i.e. the current HTML page)Copy the code

Equivalent to synchronization, js does nothing in this function, but stops for dozens of ms, like a dull person wasting some free time.

What about Ajax asynchrony? – async: true

$.ajax({
    url: '. ',
    async: true,
    success: function(responseText){console.log(responseText)}// If the request is returned, call success and print out the result.'Request sent complete')
Copy the code

On the console, simulate a slow operation: Network — slow 3G, as shown:

Draw a picture:

async:false

V. Asynchronous form

From the example above: you can get the width by binding the onLoad event, or the SUCCESS function in Ajax. In general, there are two ways to get asynchronous results

1, stupid method: polling

2, the normal method: callback

The form of a callback

  • The error-first form of node.js
fs.readFile('./1.txt', (error, content)=>{
    if(error){// Failed}else{// success}})Copy the code

-jQuery success/error form

$.ajax({
     url:'/xxx',
     success:()=>{},
     error: ()=>{}
 })
Copy the code

– done/fail/always in jQuery

$.ajax({
     url:'/xxx',
 }).done( ()=>{} ).fail( ()=>{} ).always( ()=> {})
Copy the code
  • Then form of Prosmise
$.ajax({
     url:'/xxx',
 }).then( ()=>{}, ()=>{} ).then( ()=>{})
Copy the code

Vi. How to handle exceptions?

  • How do I use multiple SUCCESS functions?
  • How do you handle exceptions in the case of multiple successful callbacks?

Return yourself to Promise

function ajax() {returnNew Promise((resolve, reject)=>{resolve, reject})} var Promise = ajax() Promise. Then (successFn, errorFn)Copy the code
  • Promise:
  • Promise/A + specification:

async / await

function buyFruit() {returnNew Promise((resolve, reject)=>{resolve, reject})} var Promise = await ajax()Copy the code
async functon fn(){
    var result = await buyFruit()
    return result
}
var r = await fn()
console.log(r)
Copy the code