柚子快報(bào)邀請(qǐng)碼778899分享:AJAX知識(shí)點(diǎn)(詳解)
柚子快報(bào)邀請(qǐng)碼778899分享:AJAX知識(shí)點(diǎn)(詳解)
???????歡迎來(lái)到我的博客,很高興能夠在這里和您見面!希望您在這里可以感受到一份輕松愉快的氛圍,不僅可以獲得有趣的內(nèi)容和知識(shí),也可以暢所欲言、分享您的想法和見解。
非常期待和您一起在這個(gè)小小的網(wǎng)絡(luò)世界里共同探索、學(xué)習(xí)和成長(zhǎng)。??? ?? 歡迎訂閱本專欄 ?? ?
前言
本欄目是根據(jù)黑馬程序員的網(wǎng)課來(lái)整理的筆記,也會(huì)結(jié)合我的一些個(gè)人見解,來(lái)記錄自己學(xué)習(xí)AJAX的過程,俗話說,好記性不如爛筆頭,小鄭喜歡在學(xué)習(xí)的過程中記筆記,記下自己在學(xué)習(xí)過程中難以理解的知識(shí)點(diǎn),反復(fù)練習(xí),加深印象,希望廣大網(wǎng)友一起監(jiān)督學(xué)習(xí),互相進(jìn)步!
目錄
1. 同步代碼和異步代碼
2. 回調(diào)函數(shù)地獄
3. Promise-鏈?zhǔn)秸{(diào)用
4. async 函數(shù)和 await
5. async 函數(shù)和 await 捕獲錯(cuò)誤
6.?事件循環(huán)
7. 宏任務(wù)與微任務(wù)
8. Promise.all 靜態(tài)方法
1. 同步代碼和異步代碼
同步代碼:逐行執(zhí)行,需原地等待結(jié)果后,才繼續(xù)向下執(zhí)行 異步代碼:調(diào)用后耗時(shí),不阻塞代碼繼續(xù)執(zhí)行(不必原地等待),在將來(lái)完成后觸發(fā)回調(diào)函數(shù)傳遞結(jié)果 回答代碼打印順序:發(fā)現(xiàn)異步代碼接收結(jié)果,使用的都是回調(diào)函數(shù)
案例:
const result = 0 + 1
console.log(result)
setTimeout(() => {
console.log(2)
}, 2000)
document.querySelector('.btn').addEventListener('click', () => {
console.log(3)
})
document.body.style.backgroundColor = 'pink'
console.log(4)
結(jié)果:1, 4, 2
按鈕點(diǎn)擊一次打印一次 3
2. 回調(diào)函數(shù)地獄
概念:在回調(diào)函數(shù)中嵌套回調(diào)函數(shù),一直嵌套下去就形成了回調(diào)函數(shù)地獄 缺點(diǎn):可讀性差,異常無(wú)法捕獲,耦合性嚴(yán)重,牽一發(fā)動(dòng)全身
axios({ url: 'http://hmajax.itheima.net/api/province' }).then(result => {
const pname = result.data.list[0]
document.querySelector('.province').innerHTML = pname
// 獲取第一個(gè)省份默認(rèn)下屬的第一個(gè)城市名字
axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } }).then(result => {
const cname = result.data.list[0]
document.querySelector('.city').innerHTML = cname
// 獲取第一個(gè)城市默認(rèn)下屬第一個(gè)地區(qū)名字
axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } }).then(result => {
document.querySelector('.area').innerHTML = result.data.list[0]
})
})
})
3. Promise-鏈?zhǔn)秸{(diào)用
概念:依靠 then() 方法會(huì)返回一個(gè)新生成的 Promise 對(duì)象特性,繼續(xù)串聯(lián)下一環(huán)任務(wù),直到結(jié)束 細(xì)節(jié):then() 回調(diào)函數(shù)中的返回值,會(huì)影響新生成的 Promise 對(duì)象最終狀態(tài)和結(jié)果 好處:通過鏈?zhǔn)秸{(diào)用,解決回調(diào)函數(shù)嵌套問題
核心代碼:
/**
* 目標(biāo):掌握Promise的鏈?zhǔn)秸{(diào)用
* 需求:把省市的嵌套結(jié)構(gòu),改成鏈?zhǔn)秸{(diào)用的線性結(jié)構(gòu)
*/
// 1. 創(chuàng)建Promise對(duì)象-模擬請(qǐng)求省份名字
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('北京市')
}, 2000)
})
// 2. 獲取省份名字
const p2 = p.then(result => {
console.log(result)
// 3. 創(chuàng)建Promise對(duì)象-模擬請(qǐng)求城市名字
// return Promise對(duì)象最終狀態(tài)和結(jié)果,影響到新的Promise對(duì)象
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result + '--- 北京')
}, 2000)
})
})
// 4. 獲取城市名字
p2.then(result => {
console.log(result)
})
// then()原地的結(jié)果是一個(gè)新的Promise對(duì)象
console.log(p2 === p)
4. async 函數(shù)和 await
async function?聲明創(chuàng)建一個(gè)綁定到給定名稱的新異步函數(shù)。函數(shù)體內(nèi)允許使用 await?關(guān)鍵字,這使得我們可以更簡(jiǎn)潔地編寫基于 promise 的異步代碼,并且避免了顯式地配置 promise 鏈的需要。
概念:在 async 函數(shù)內(nèi),使用 await 關(guān)鍵字取代 then 函數(shù),等待獲取 Promise 對(duì)象成功狀態(tài)的結(jié)果值 做法:使用 async 和 await 解決回調(diào)地獄問題 核心代碼:
/**
* 目標(biāo):掌握async和await語(yǔ)法,解決回調(diào)函數(shù)地獄
* 概念:在async函數(shù)內(nèi),使用await關(guān)鍵字,獲取Promise對(duì)象"成功狀態(tài)"結(jié)果值
* 注意:await必須用在async修飾的函數(shù)內(nèi)(await會(huì)阻止"異步函數(shù)內(nèi)"代碼繼續(xù)執(zhí)行,原地等待結(jié)果)
*/
// 1. 定義async修飾函數(shù)
async function getData() {
// 2. await等待Promise對(duì)象成功的結(jié)果
const pObj = await axios({url: 'http://hmajax.itheima.net/api/province'})
const pname = pObj.data.list[0]
const cObj = await axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }})
const cname = cObj.data.list[0]
const aObj = await axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }})
const areaName = aObj.data.list[0]
document.querySelector('.province').innerHTML = pname
document.querySelector('.city').innerHTML = cname
document.querySelector('.area').innerHTML = areaName
}
getData()
5. async 函數(shù)和 await 捕獲錯(cuò)誤
try 和 catch 的作用:語(yǔ)句標(biāo)記要嘗試的語(yǔ)句塊,并指定一個(gè)出現(xiàn)異常時(shí)拋出的響應(yīng)
try {
// 要執(zhí)行的代碼
} catch (error) {
// error 接收的是,錯(cuò)誤消息
// try 里代碼,如果有錯(cuò)誤,直接進(jìn)入這里執(zhí)行
}
6.?事件循環(huán)
作用:事件循環(huán)負(fù)責(zé)執(zhí)行代碼,收集和處理事件以及執(zhí)行隊(duì)列中的子任務(wù) 原因:JavaScript 單線程(某一刻只能執(zhí)行一行代碼),為了讓耗時(shí)代碼不阻塞其他代碼運(yùn)行,設(shè)計(jì)了事件循環(huán)模型 概念:執(zhí)行代碼和收集異步任務(wù)的模型,在調(diào)用??臻e,反復(fù)調(diào)用任務(wù)隊(duì)列里回調(diào)函數(shù)的執(zhí)行機(jī)制,就叫事件循環(huán)
/**
* 目標(biāo):閱讀并回答執(zhí)行的順序結(jié)果
*/
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
console.log(3)
setTimeout(() => {
console.log(4)
}, 2000)
console.log(5)
結(jié)果 1 3 5 2 4
這段代碼的流程如下:
執(zhí)行1的時(shí)候,可以直接放入調(diào)用棧
當(dāng)實(shí)現(xiàn)回調(diào)函數(shù)的時(shí)候,因?yàn)椴恢酪却嗑茫圆粫?huì)一直等待,將回調(diào)函數(shù)2放入宿主環(huán)境,然后放入任務(wù)隊(duì)列
接著執(zhí)行3,5,再將回調(diào)函數(shù)4放入宿主環(huán)境
當(dāng)調(diào)用棧為空的時(shí)候,調(diào)研棧會(huì)不斷地訪問任務(wù)隊(duì)列,此時(shí)才將回調(diào)函數(shù)放入調(diào)用棧
7. 宏任務(wù)與微任務(wù)
ES6 之后引入了 Promise 對(duì)象, 讓 JS 引擎也可以發(fā)起異步任務(wù) 異步任務(wù)劃分為了
宏任務(wù):由瀏覽器環(huán)境執(zhí)行的異步代碼 微任務(wù):由 JS 引擎環(huán)境執(zhí)行的異步代碼 宏任務(wù)和微任務(wù)具體劃分:
/**
* 目標(biāo):閱讀并回答打印的執(zhí)行順序
*/
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
const p = new Promise((resolve, reject) => {
resolve(3)
})
p.then(res => {
console.log(res)
})
console.log(4)
流程:
因?yàn)閟crpit是腳本執(zhí)行文件,所以放入宿主環(huán)境,接著把整段代碼都放進(jìn)宏任務(wù)隊(duì)列
此時(shí)調(diào)用棧為空,所以不斷訪問宏任務(wù)隊(duì)列,console.log(1)上調(diào)用棧 執(zhí)行完就退出
接著執(zhí)行setTimeout,因?yàn)槭腔卣{(diào)函數(shù),所以放入宏任務(wù)隊(duì)列
接著執(zhí)行const p .....? 因?yàn)閜romise本身是同步的,所以執(zhí)行console.log(3)?
接著執(zhí)行p.then... 因?yàn)閠hem是異步的,所以進(jìn)入宏任務(wù)隊(duì)列
console.log(5)上調(diào)用棧
因?yàn)槲⒎?wù)隊(duì)列更接近js引擎,所以先執(zhí)行微服務(wù)隊(duì)列(微服務(wù)隊(duì)列比宏任務(wù)隊(duì)列先執(zhí)行)
所以執(zhí)行4再執(zhí)行5
注意:宏任務(wù)每次在執(zhí)行同步代碼時(shí),產(chǎn)生微任務(wù)隊(duì)列,清空微任務(wù)隊(duì)列任務(wù)后,微任務(wù)隊(duì)列空間釋放!
下一次宏任務(wù)執(zhí)行時(shí),遇到微任務(wù)代碼,才會(huì)再次申請(qǐng)微任務(wù)隊(duì)列空間放入回調(diào)函數(shù)消息排隊(duì)
總結(jié):一個(gè)宏任務(wù)包含微任務(wù)隊(duì)列,他們之間是包含關(guān)系,不是并列關(guān)系
事件循環(huán)經(jīng)典面試題
// 目標(biāo):回答代碼執(zhí)行順序
console.log(1)
setTimeout(() => {
console.log(2)
const p = new Promise(resolve => resolve(3))
p.then(result => console.log(result))
}, 0)
const p = new Promise(resolve => {
setTimeout(() => {
console.log(4)
}, 0)
resolve(5)
})
p.then(result => console.log(result))
const p2 = new Promise(resolve => resolve(6))
p2.then(result => console.log(result))
console.log(7)
結(jié)果:1 7 5 6 2 3 4?
流程:
先執(zhí)行console.log(1)
接著回調(diào)函數(shù)setTimeout放入宿主環(huán)境,再放入宏任務(wù)隊(duì)列
接著執(zhí)行const? p ..... 放入微任務(wù)隊(duì)列 因?yàn)槔锩嬗谢卣{(diào)函數(shù),所以將里面的回調(diào)函數(shù)放入宏任務(wù)隊(duì)列 Promise中的resolve返回的是完成
接著執(zhí)行p.then,放入微任務(wù)隊(duì)列
接著執(zhí)行p2.then 放入微任務(wù)隊(duì)列
接著執(zhí)行console.log(7)
此時(shí)調(diào)用棧已經(jīng)沒有東西了,不斷訪問微任務(wù)隊(duì)列
依次執(zhí)行p.then 返回5? p.then 返回6
只有微任務(wù)清空才會(huì)執(zhí)行宏任務(wù)隊(duì)列
接著執(zhí)行宏任務(wù)隊(duì)列,console.log(2)? 因?yàn)榛卣{(diào)函數(shù)里面有Promise 所以將其放入微任務(wù)隊(duì)列
先執(zhí)行微任務(wù)隊(duì)列 所以輸出3
最后剩下宏任務(wù)隊(duì)列的4
8. Promise.all 靜態(tài)方法
概念:合并多個(gè) Promise 對(duì)象,等待所有同時(shí)成功完成(或某一個(gè)失?。?,做后續(xù)邏輯
Promise.all 什么時(shí)候使用?
合并多個(gè) Promise 對(duì)象并等待所有同時(shí)成功的結(jié)果,如果有一個(gè)報(bào)錯(cuò)就會(huì)最終為失敗狀態(tài),當(dāng)需要同時(shí)渲染多個(gè)接口數(shù)據(jù)同時(shí)到網(wǎng)頁(yè)上時(shí)使用
??????小鄭是普通學(xué)生水平,如有紕漏,歡迎各位大佬評(píng)論批評(píng)指正!???
???如果覺得這篇文對(duì)你有幫助的話,也請(qǐng)給個(gè)點(diǎn)贊、收藏下吧,非常感謝!? ? ?
柚子快報(bào)邀請(qǐng)碼778899分享:AJAX知識(shí)點(diǎn)(詳解)
好文閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。