摘要:同步和異步先說個傻子的故事有個傻子,第一次用某雷下載大片,就是大人看的片,咳咳咳。。。
1.同步和異步 1.1先說個傻子的故事
有個傻子,第一次用某雷下載大片,就是大人看的片,咳咳咳。。。 某雷告訴他,下載時間要倆小時,傻子心想,要倆小時吶,我第一次用某雷,我得盯著它下載,啥也不能干 于是傻子就干瞪著電腦,等著片下完,這倆小時,傻子啥也沒干 后來,傻子變聰明了,他想,反正某雷在幫他下載,這倆小時,他完全可以干干其他事情啊,比如學學計算機知識呀等等 等某雷下完了,再回來看唄 于是傻子潛心研究計算機知識,直到有一天他看到了有關于異步的知識,突然間明白了
原來他等待某雷下完,啥也不干的過程就叫做同步
后來他在某雷下載過程中自學計算機知識的過程就叫做異步
同步
英文:Synchronization
wiki解釋:指在一個系統中所發生的事件(event),之間進行協調,在時間上出現一致性與統一化的現象。
是不是很難理解?
其實就是代碼要等待到結果,才能繼續進行【你可以理解為同步阻塞了代碼繼續執行】
異步
英文:Asynchronization【在同步前面加了個A】
wiki解釋就不貼了,有興趣的朋友可以自己搜索看一下,反正我看的也挺頭疼
其實就是代碼不用等待到結果,就能繼續進行【你可以理解為異步不阻塞代碼繼續執行】
啥意思咧,讓我們看個大家都見過的例子
function wait() { setTimeout(() => console.log(this), 3000) } wait() // 三秒鐘后,得到結果 console.log(1) // 如果沒有異步的話,我得等三秒鐘才能執行,所以,感謝異步2.常見的異步問題 2.1圖片加載問題
// 前提條件:用戶的瀏覽器第一次請求這個圖片,也就是用戶的瀏覽器未緩存 document.getElementsByTagNames("img")[0].width // 寬度為 0
為什么width會為0呢?
因為js運行的時候,img并沒有下載完畢
解決方案
let imgNode = document.getElementsByTagName("img")[0] imgNode.addEventListener("onload",function () { console.log(this.width) })2.2 面試題常考的異步問題
// 假設有5個li let liList = document.querySelectorAll("li") for (var i = 0; i < liList.length; i++) { liList[i].onclick = function () { console.log(i) // 5 5 5 5 5 } }
為什么呢?
因為onclick事件是異步處理的,用戶觸發onclick事件時,循環早已結束,此時的i是5
解決方案一【立即執行函數創建獨立作用域】
// 假設有5個li let liList = document.querySelectorAll("li") for (var i = 0; i < liList.length; i++) { !(function (j) { liList[j].onclick = function () { console.log(j) // 5 5 5 5 5 } })(i) }
解決方案二【使用let】
// 假設有5個li let liList = document.querySelectorAll("li") for (let i = 0; i < liList.length; i++) { liList[i].onclick = function () { console.log(i) // 5 5 5 5 5 } }3.拿到異步結果的方式 —— 回調
請見回調是個什么鬼?
4.Promise請見淺析Promise
5.async / await 語句 5.1 粗略了解awaitmdn解釋:await 操作符用于等待一個Promise 對象。它只能在異步函數 async function 中使用
但是await究竟做了什么事情呢?
let setPromise = function () { return new Promise((resolve, reject) => { // 你的異步代碼 setTimeout(() => { resolve("success") }, 10000) }) } let result = await setPromise() 如果你這個時候在控制臺不斷輸入result。 控制臺會不斷地報錯 控制臺報錯:result is not defined 直到10s后,才能成功
為啥報錯呢?命名let result了呀
因為await在等待setPromise()完成后,才會執行let result =
也就是說await 讓前面的 let 和 = 異步了
可能你會問:
這樣一搞,result也異步了,那我豈不是還要回調?
那么再來看下一個問題
let setPromise = function () { return new Promise((resolve, reject) => { // 你的異步代碼 setTimeout(() => { resolve("success") }, 10000) }) } let result = await setPromise() console.log(1) // 請問這句代碼是在10秒后被執行,還是立即執行?
答案:10s后執行
5.2 所以await究竟能干嘛await改變了整個代碼的執行順序.
它可以讓你用同步寫代碼的方式去寫異步代碼
如果你在一個函數內使用了await,那么你最好在一個函數的前面加上async
let setPromise = function () { return new Promise((resolve, reject) => { // 你的異步代碼 setTimeout(() => { resolve("success") }, 2000) }) } function test() { return result = await setPromise() } console.log(3)
控制臺直接會報錯:Uncaught SyntaxError: await is only valid in async function
啥意思咧 —— await只允許在 async function 內使用
也就是說,要在函數聲明的時候就加上 async
async function test() { let result = await setPromise() }5.4 Promise異步操作失敗的情況
let setPromise = function () { return new Promise((resolve, reject) => { // 你的異步代碼 setTimeout(() => { reject.call(undefined) }, 2000) }) } let result = await setPromise() console.log(result) // 瀏覽器又報錯了 Uncaught (in promise) undefined
因為沒有then/catch來處理Promise異步操作失敗的結果
所以我們這次使用try...catch...語句
let setPromise = function () { return new Promise((resolve, reject) => { // 你的異步代碼 setTimeout(() => { reject.call(undefined) }, 2000) }) } try { let result = await setPromise() console.log(result) } catch(rejected) { // 觸發這一句 console.log("error") }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93765.html
摘要:異步時序問題吾輩的博客原文場景死后我們必升天堂,因為活時我們已在地獄。關鍵點異步操作得到結果的時間順序是不確定的如果觸發事件的頻率較高異步操作的時間過長出現這種問題怎么解決既然關鍵點由兩個要素組成,那么,只要破壞了任意一個即可。 JavaScript 異步時序問題 吾輩的博客原文:https://blog.rxliuli.com/p/de... 場景 死后我們必升天堂,因為活時我們已...
摘要:同步與異步以上為同步代碼,函數必須等函數執行完畢后才能執行。異步回調產生的結果就是,函數的調用并不直接返回結果,而往往是交給回調函數進行異步處理。 同步與異步: function a(){} function b(){} a(); b(); 以上為同步代碼,函數b必須等函數a執行完畢后才能執行。 function a(){ ...
摘要:同步和異步先說個傻子的故事有個傻子,第一次用某雷下載大片,就是大人看的片,咳咳咳。。。 1.同步和異步 1.1先說個傻子的故事 有個傻子,第一次用某雷下載大片,就是大人看的片,咳咳咳。。。 某雷告訴他,下載時間要倆小時,傻子心想,要倆小時吶,我第一次用某雷,我得盯著它下載,啥也不能干 于是傻子就干瞪著電腦,等著片下完,這倆小時,傻子啥也沒干 后來,傻子變聰明了,他想,反正某雷在幫他下...
摘要:事件循環事件循環是指主線程重復從消息隊列中取消息執行的過程。事件觸發時,表示異步任務完成,會將事件監聽器函數封裝成一條消息放到消息隊列中,等待主線程執行。 一. 單線程 我們常說JavaScript是單線程的。 所謂單線程,是指在JS引擎中負責解釋和執行JavaScript代碼的線程只有一個。不妨叫它主線程。 但是實際上還存在其他的線程。例如:處理AJAX請求的線程、處理DOM事件的線...
摘要:例如處理請求的線程處理事件的線程定時器線程讀寫文件的線程例如在中等等。事件循環事件循環是指主線程重復從消息隊列中取消息執行的過程。事件觸發時,表示異步任務完成,會將事件監聽器函數封裝成一條消息放到消息隊列中,等待主線程執行。 一. 單線程 我們常說JavaScript是單線程的。 所謂單線程,是指在JS引擎中負責解釋和執行JavaScript代碼的線程只有一個。不妨叫它主線程。 但是實...
閱讀 1039·2021-09-13 10:29
閱讀 3389·2019-08-29 18:31
閱讀 2633·2019-08-29 11:15
閱讀 3011·2019-08-26 13:25
閱讀 1368·2019-08-26 12:00
閱讀 2293·2019-08-26 11:41
閱讀 3376·2019-08-26 10:31
閱讀 1488·2019-08-26 10:25