First of all, let’s start by thinking about a few questions. When we think about the purpose of the question, we can first think about what knowledge point the question is examining, and then we can understand the knowledge point through the question
Js async/event loop /Promise
Let’s look at some interview questions and learn from them:
- What’s the difference between synchronous and asynchronous?
- Handwritten Promise load an image?
- What are the scenarios where asynchrony is used at the front end?
- Please describe the mechanism of event loop (event loop/event polling)
- What is a macro task? What are microtasks and what are the differences?
- What are the three states of a Promise? How does it change?
Knowledge:
- Single threaded and asynchronous
- Application scenarios
- The callback hell and Promise
- event loop
- Promise the advanced
- The use of async/await
- Cognition and differentiation of microtasks/macrotasks
Single threaded and asynchronous
Asynchronous because of the single thread of JS
-
JS is a single-threaded language that can only do one thing at a time
For example, if we make an Ajax request and a timer waits for a second, if it's synchronous, it gets stuck loading an image or ajax, you can't click it, you can't drag it, you can't execute JS, that's the nature of a single-threaded language.Copy the code
-
Browsers and NodeJS already support JS startup processes, such as Web workers; But it doesn’t change the fact that JS is single threaded
-
Because JS can modify the DOM structure, DOM rendering of JS shares the same thread. DOM must be stopped during JS execution and JS must be stopped during DOM rendering
So, when we encounter waiting (network request, scheduled task), we need asynchronous, solve the problem of single thread JS, callback function form synchronous asynchronous example: asynchronous can start a timer or request data, synchronous can put an alert (.). , you'll find that the code behind alert is blocked.Copy the code
Asynchronous and synchronous:
- JS based is a single threaded language
- Asynchrony does not block code execution
- Synchronization blocks code execution
Application scenarios
- Web requests, such as Ajax, image loading
- A scheduled task, such as setTimeout
Network request:
console.log('start')
$.get('./detail.json',function(data1){
console.log(data1)
})
console.log('end')
Copy the code
Image loading:
console.log('start')
let img = document.createElement('img')
img.onload = function(){
console.log('loaded')
}
img.src = '/xxx.png'
console.log('end')
Copy the code
The timer ~
Callback hell
The old-fashioned way of nesting layer upon layer:It’s complicated, and that’s where peomise comes in:
Peomise solves callback hell: that is, the problem of callback nesting;
Handwritten Promise loads an image
Return loadImg(SRC){return new Promise(resolve,reject) => {resolve,reject) Const img = document.createElement('img') img.onload = () => {resolve(img)// img.onerror = () => {reject(new Error(' reject '${SRC}'))} img. SRC = SRC})} loadImg(url) So I can then const url1 = 'https://img.mukewang.com/5a9fc8070001a82402060220-140-140.jpg' const url2 = 'https://img3.mukewang.com/5a9fc8070001a82402060220-100-100.jpg' loadImg(url1).then(img1 => { console.log(img1.width) Then (img1 => {console.log(img1.height) return loadImg(url2) }). Then (img2 => {console.log(img2.width) return img2}). Then (img2 => {console.log(img2.width) return img2}). }).catch(ex => console.error(ex))Copy the code
Promise
(1) The state of Promise
- Promises come in three states
- The manifestation and change of state
- Effects of then and catch on state
Pending -> Resolved or Pending -> RejectedCopy the code
// Code: const p1 = new Promise((resolve,reject) =>{}) console.log('p1',p1) // p1 Promise{<pending>} const p2 = new Promise((resolve,reject) =>{setTimeout(()=>{resolve()})}) console.log('p2',p2) // p2 Promise{<pending>} is still a pending // When we click on it, PromiseStatus is resolved Log ('p2-setTimeout',p2)}) // P2-setTimeout Promise{<resolved>:undefined} Const p3 = new Promise((resolve,reject) =>{setTimeout(()=>{reject()})}) console.log('p3',p3) // P3 Promise{<pending>}, PromiseStatus is a rejected setTimeout(()=>{console.log('p3-setTimeout',p3)}) // p3-setTimeout Promise{<rejected>:undefined}Copy the code
- The state of pengding, which does not trigger then and catch
- Resolved state, which triggers subsequent THEN callbacks
- The Rejected state triggers the subsequent catch callback
Resolve ('p1',p1)//p1 Promise{<resolved>:100} Log ('data',data) // data 100}). Catch (err => {console.error('err',err). }) const p2 = promise. reject('err') // rejected // Log ('p2',p2)//p2 Promise{<rejected>:'err'} P2. then(data => {console.log('data2',data) // Rejected does not go}). Catch (err => {// Rejected does not go console.error('err2',err) // err2 'err' })Copy the code
(2) How do the then and catch of Promise affect the change of state
- Then return Resolved, and rejected if there is an error
- ‘Resolved’ and ‘Rejected’ when ‘error’ is returned
These two sentences are simple, but we can understand them from the following code:
Resolve (). Resolve () => {// resolved then return 100}) Resolve (). Then () => {throw new Error('err')}) // catch() Reject (). Catch (() => {// Rejected raises the catch callback console.error('catch some error')}) // Catch () throws an error, Reject (). Catch (() => {console.error('catch some error') throw new error(' err')})Copy the code
async/await
- At first, there was an asynchronous callback callback hell
- And then we use the Promise then catch chain-call, but also based on the callback function.
- Async /await is synchronous syntax, completely eliminates callback functions (synchronous writing)
Function loadImg(SRC) {const promise = new promise ((resolve, resolve, resolve) reject) => { const img = document.createElement('img') img.onload = () => { resolve(img) } img.onerror = () => { Reject (new Error(' image load failure ${SRC} '))} img.src = SRC}) return promise} // If there is an error due to this symbol, we can add one in front of it! No. : async function loadImg3(){ const src3 = 'http://www.imooc.com/static/img/index/logo_new.png' const img3 = await loadImg(src3) return img3 } ! (async function loadImg1() { const src1 = 'http://www.imooc.com/static/img/index/logo_new.png' const img1 = await LoadImg (src1) / / promise object const src2 = 'http://www.imooc.com/static/img/index/logo_new.png' const img2 = await LoadImg (src2) const img3 = await loadImg3() // async function console.log(img1, Img2,' synchronous writing ')})() // await can be appended as well as promise objectsCopy the code
Async /await and Promise relationship
- Async /await is the ultimate weapon against asynchronous callbacks
- Promise and Promise are not mutually exclusive
- The two complement each other
Async function fn1() {return 100 Resolve (100) Both return a Promise. Resolve (100) both return a Promise. } const res1 = fn1() console.log(res1) // Promise{<resolved>:100} -> Async returns a Promise object // Await followed by promise, value, async function all three! (async function(){const p1 = Promise resolve(300) const data = await p1 // await = await Then const data2 = await fn1() // async function console.log('data',data,data1,data2) // data 300 400 100 })() // try... catch... Equivalent to a Promise catch! (async function (){ const p4 = Promise.reject('err1') // rejected try { const res = await p4 console.log(res) // } catch (ex){console.error(ex) // err1}})()Copy the code
To sum up, the two complement each other for the following reasons:
- The async function is executed and returns a Promise object
- Await is equivalent to then of Promise
- try… Catch catches exceptions, replacing the catch of Promise
Nature of asynchrony
event loop
- Scenario question – Connection of promise then and catch
2. Scenario-async /await syntax3. The sequence of promise/setTimeout4. Scenario questions – plus async/await order questions (thinking about output)
Event loop (Event loop/Event polling)
- Js runs in a single thread
- Asynchrony is implemented based on callbacks
- The Event loop is how asynchronous callbacks are implemented
How is JS executed?
- From front to back, line by line
- If a line of execution fails, stop the execution of the following code
- Execute synchronous code before asynchrony (asynchrony via callback)
So let’s get familiar with this code before we talk about Event Loop
console.log('hi')
setTimeout(function cd1(){
consol.log('cd1')
},5000)
console.log('bye')
Copy the code
And this diagram is a diagram of the flow through which we execute the code
- Synchronize the execution of code. First, our first line of console.log(‘Hi’) will be pushed onto the call stack (1), and the call stack will execute this line of code, displaying Hi at console (2) output, and then the call stack (1) will pop the first line off the call stack
- Processing of asynchronous code. The second line of setTimeout is then placed on the execution stack, with a function cb1 inside. But because it’s asynchronous, it puts the timer(cb1) in WebAPIs (3), the stack pops up setTimeout, and after 5 seconds it puts the timer(CB1) in the function queue.
- Execution of the remaining synchronized code. The third piece of code console.log(‘Bye’) is then pushed into the call stack, which executes that line, outputs it to the console, and pops out of the call stack when it’s done.
- Continue with the asynchronous code. But at this point, the second part of the code is still in WebAPI; Because at this time our call stack is cleared and there are no events in it, our Event loop mechanism will be activated. Once our synchronous code is executed and the call stack is cleared, our event loop mechanism will be activated immediately. The event loop loops over and over again, looking for any functions in the function queue that need to be executed.
- Execution of asynchronous code. When an event is triggered, it bounces from the WebAPI into the function queue; When eventLoop finds an event in the function queue, it immediately adds the function to the stack to execute. The execution stack analyzes timer(CB1), divided into functions cb1 and console.log. The internal console is executed, the output is printed on the console, and the console is cleared. There is only one line of print code in the function, so the function is finished. So I’m going to pop cb1 off the stack. The entire code is executed.
conclusion
- Synchronizes code line by line on the CallStack
- When asynchrony occurs, it “logs”, pops onto WebAPIs, and waits for the right time (timing, network request, etc.)
- When the time is right, it moves to the Callback Queue
- If the Call Stack is empty (that is, the synchronized code is finished), the Event Loop starts working
- The Event Loop checks the Callback Queue and moves it to the Call Stack for execution if there is an Event
- Event Loop continues the search (like a perpetual motion machine)
DOM events and Event loops
Whenever a callback is used, it is based on the Event loop
- JS is single threaded
- DOM events are also based on event loops because they also use callbacks (such as when the user clicked)
- Asynchrony (setTimeout, Ajax, etc.) is also based on event loops