AJAX知识点(详解)

07-19 1483阅读

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

AJAX知识点(详解)

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

 

前言

本栏目是根据黑马程序员的网课来整理的笔记,也会结合我的一些个人见解,来记录自己学习AJAX的过程,俗话说,好记性不如烂笔头,小郑喜欢在学习的过程中记笔记,记下自己在学习过程中难以理解的知识点,反复练习,加深印象,希望广大网友一起监督学习,互相进步!

目录

1. 同步代码和异步代码

2. 回调函数地狱

3. Promise-链式调用

4. async 函数和 await

5. async 函数和 await 捕获错误

6. 事件循环

7. 宏任务与微任务

8. Promise.all 静态方法



1. 同步代码和异步代码

  1. 同步代码:逐行执行,需原地等待结果后,才继续向下执行

  2. 异步代码:调用后耗时,不阻塞代码继续执行(不必原地等待),在将来完成后触发回调函数传递结果

  3. 回答代码打印顺序:发现异步代码接收结果,使用的都是回调函数

案例:

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)

结果:1, 4, 2

按钮点击一次打印一次 3

2. 回调函数地狱

  1. 概念:在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱

  2. 缺点:可读性差,异常无法捕获,耦合性严重,牵一发动全身

axios({ url: 'http://hmajax.itheima.net/api/province' }).then(result => {
  const pname = result.data.list[0]
  document.querySelector('.province').innerHTML = pname
  // 获取第一个省份默认下属的第一个城市名字
  axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } }).then(result => {
    const cname = result.data.list[0]
    document.querySelector('.city').innerHTML = cname
    // 获取第一个城市默认下属第一个地区名字
    axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } }).then(result => {
      document.querySelector('.area').innerHTML = result.data.list[0]
    })
  })
})

3. Promise-链式调用

  1. 概念:依靠 then() 方法会返回一个新生成的 Promise 对象特性,继续串联下一环任务,直到结束

  2. 细节:then() 回调函数中的返回值,会影响新生成的 Promise 对象最终状态和结果

  3. 好处:通过链式调用,解决回调函数嵌套问题

AJAX知识点(详解)

AJAX知识点(详解)

核心代码:

/**
 * 目标:掌握Promise的链式调用
 * 需求:把省市的嵌套结构,改成链式调用的线性结构
*/
// 1. 创建Promise对象-模拟请求省份名字
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('北京市')
  }, 2000)
})
// 2. 获取省份名字
const p2 = p.then(result => {
  console.log(result)
  // 3. 创建Promise对象-模拟请求城市名字
  // return Promise对象最终状态和结果,影响到新的Promise对象
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(result + '--- 北京')
    }, 2000)
  })
})
// 4. 获取城市名字
p2.then(result => {
  console.log(result)
})
// then()原地的结果是一个新的Promise对象
console.log(p2 === p)

4. async 函数和 await

async function 声明创建一个绑定到给定名称的新异步函数。函数体内允许使用 await 关键字,这使得我们可以更简洁地编写基于 promise 的异步代码,并且避免了显式地配置 promise 链的需要。

  1. 概念:在 async 函数内,使用 await 关键字取代 then 函数,等待获取 Promise 对象成功状态的结果值

  2. 做法:使用 async 和 await 解决回调地狱问题

  3. 核心代码:

/**
 * 目标:掌握async和await语法,解决回调函数地狱
 * 概念:在async函数内,使用await关键字,获取Promise对象"成功状态"结果值
 * 注意:await必须用在async修饰的函数内(await会阻止"异步函数内"代码继续执行,原地等待结果)
*/
// 1. 定义async修饰函数
async function getData() {
  // 2. await等待Promise对象成功的结果
  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 函数和 await 捕获错误

try 和 catch 的作用:语句标记要尝试的语句块,并指定一个出现异常时抛出的响应

try {
  // 要执行的代码
} catch (error) {
  // error 接收的是,错误消息
  // try 里代码,如果有错误,直接进入这里执行
}

6. 事件循环

  1. 作用:事件循环负责执行代码,收集和处理事件以及执行队列中的子任务

  2. 原因:JavaScript 单线程(某一刻只能执行一行代码),为了让耗时代码不阻塞其他代码运行,设计了事件循环模型

  3. 概念:执行代码和收集异步任务的模型,在调用栈空闲,反复调用任务队列里回调函数的执行机制,就叫事件循环

/**
 * 目标:阅读并回答执行的顺序结果
*/
console.log(1)
setTimeout(() => {
  console.log(2)
}, 0)
console.log(3)
setTimeout(() => {
  console.log(4)
}, 2000)
console.log(5)

AJAX知识点(详解)

结果 1 3 5 2 4

这段代码的流程如下:

执行1的时候,可以直接放入调用栈

当实现回调函数的时候,因为不知道要等待多久,所以不会一直等待,将回调函数2放入宿主环境,然后放入任务队列

接着执行3,5,再将回调函数4放入宿主环境

当调用栈为空的时候,调研栈会不断地访问任务队列,此时才将回调函数放入调用栈

7. 宏任务与微任务

  1. ES6 之后引入了 Promise 对象, 让 JS 引擎也可以发起异步任务

  2. 异步任务划分为了

    • 宏任务:由浏览器环境执行的异步代码

    • 微任务:由 JS 引擎环境执行的异步代码

  3. 宏任务和微任务具体划分:

AJAX知识点(详解)

/**
 * 目标:阅读并回答打印的执行顺序
*/
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)

AJAX知识点(详解)

流程:

因为scrpit是脚本执行文件,所以放入宿主环境,接着把整段代码都放进宏任务队列

此时调用栈为空,所以不断访问宏任务队列,console.log(1)上调用栈 执行完就退出

接着执行setTimeout,因为是回调函数,所以放入宏任务队列

接着执行const p .....  因为promise本身是同步的,所以执行console.log(3) 

接着执行p.then... 因为them是异步的,所以进入宏任务队列

console.log(5)上调用栈

因为微服务队列更接近js引擎,所以先执行微服务队列(微服务队列比宏任务队列先执行)

所以执行4再执行5

注意:宏任务每次在执行同步代码时,产生微任务队列,清空微任务队列任务后,微任务队列空间释放!

下一次宏任务执行时,遇到微任务代码,才会再次申请微任务队列空间放入回调函数消息排队

总结:一个宏任务包含微任务队列,他们之间是包含关系,不是并列关系

事件循环经典面试题

// 目标:回答代码执行顺序
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)

AJAX知识点(详解)

结果:1 7 5 6 2 3 4 

流程:

先执行console.log(1)

接着回调函数setTimeout放入宿主环境,再放入宏任务队列

接着执行const  p ..... 放入微任务队列 因为里面有回调函数,所以将里面的回调函数放入宏任务队列 Promise中的resolve返回的是完成

接着执行p.then,放入微任务队列

接着执行p2.then 放入微任务队列

接着执行console.log(7)

此时调用栈已经没有东西了,不断访问微任务队列

依次执行p.then 返回5  p.then 返回6

只有微任务清空才会执行宏任务队列

接着执行宏任务队列,console.log(2)  因为回调函数里面有Promise 所以将其放入微任务队列

先执行微任务队列 所以输出3

最后剩下宏任务队列的4

8. Promise.all 静态方法

概念:合并多个 Promise 对象,等待所有同时成功完成(或某一个失败),做后续逻辑

AJAX知识点(详解)

Promise.all 什么时候使用?

合并多个 Promise 对象并等待所有同时成功的结果,如果有一个报错就会最终为失败状态,当需要同时渲染多个接口数据同时到网页上时使用

❤️❤️❤️小郑是普通学生水平,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

AJAX知识点(详解)

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]