当前位置: 首页>编程语言>正文

同步、异步与Promise

1 同步

  • 如果可以直接拿到结果,那就是同步
  • 实例: 在医院挂号,拿到号才会离开窗口,无论等待时间多久,不拿到结果是不会离开的

宏任务与微任务

  • 宏任务:setTimeout setInterval Ajax DOM事件
  • 微任务:Promise async/await
  • 先同步再异步,异步任务需要等待同步任务完毕后再进行
  • asyn必须与await搭配出现,否则会报错,同时,第一个await之前的代码会同步执行,之后的会异步执行
  • 异步中,先清空微任务再执行下一个宏任务,每次执行完宏任务时,先判断微任务队列是否存在微任务,若存在,先执行清空微任务队列,再执行下一个宏任务

2 异步

2.1 概念

  • 不能直接拿到结果,那就是异步
  • 实例:在餐厅等餐位时,可以拿到号去逛街
  • 可以每10分钟去餐厅问一下(轮询)
  • 可以扫码用微信接受通知(回调)

2.2 举例

2.2.1 实例:AJAX
  • request.send()之后,并不能直接得到response
  • 必须等到readyState变为4后,浏览器回头调用request.onreadystatechange函数
  • 我们才可以得到request.response
2.2.2 回调 callback
  • 自己写给自己用的函数,不是回调
  • 自己写给别人用的函数,就是回调
  • 例如request.onreadystatechange就是我写给浏览器调用的函数
2.2.3 代码实例
function f1(){}
function f2(fn){
  fn()
}
f2(f1)

分析:

  • 我没有调用f1
  • 我将f1传给了别人
  • f2调用了f1
  • 所以f1是我写给f2调用的函数,因此f1是回调

2.3 异步与回调的关系

2.3.1 关联
  • 异步任务需要在得到结果时通知JS来拿结果
  • 让JS留一个函数地址给浏览器
  • 异步任务完成时,浏览器调用该函数地址即可
  • 同时把这个结果作为参数传给该函数
  • 这个函数是我写给浏览器调用的,所以是回调函数
2.3.2 区别
  • 异步任务需要用到回调函数来通知结果
  • 但回调函数不一定只用在异步任务里
  • 回调也可以用到同步任务里
  • array.forEach(n=>console.log(n))就是同步回调

2.4 判断同步or异步

  • 如果一个函数的返回值处于
    (1)setTimeout
    (2)AJAX(即XMLHttpRequest)
    (3)AddEventListener
    这三个东西内部,,那这个函数就是异步函数

2.5 过程

  • 异步任务不能拿到结果
  • 于是我们传一个回调给异步任务
  • 异步任务完成时调用回调
  • 调用的时候把结果作为参数

2.6 异步任务有两个结果

  • 方法一:回调接受两个参数
fs.readFile('./1.txt',(error,data)=>{
  if(error){ console.log('失败');  return }
  console.log(data.toString())  // 成功
})
  • 方法二: 搞两个回调
ajax('get','/1.json',data=>{ },error=>{ })
// data=>{ }是成功回调   error=>{ }是失败回调
ajax(‘get’,'/1.json',{
  success:()=>{}, fail:()=>{}
})
// 接受一个对象,对象有两个key表示成功和失败

缺陷:以上两个方法存在三个不足之处

  • 不规范,名称五花八门,有人使用success+error,有人使用success+fail等等
  • 容易出现回调地狱,代码变得看不懂
  • 很难进行错误处理

3 Promise的用法

3.1 以AJAX为例

// 普通回调写法
ajax('get','/xxx',{
  success(response){},
  fail:(request, status) => {}
})


// Promise写法
// then 的第一个参数是success,成功则返回需要数据
// then  的第二个参数是fail,失败则将刚才的请求拿回来查找问题
ajax('get','/xxx')
  .then((respsonse)=>{},(request)=>{})
  • ajax返回了一个含有.then方法的对象

3.2 回调异步函数=>Primoise异步函数

第一步:

  • return new Promise((resolve,reject)=>{……})
  • 任务成功则调用resolve(result)
  • 任务失败则调用reject(error)
  • resolve和reject会再去调用成功和失败函数

第二步:

  • 使用.then(success,fail)传入成功和失败函数

3.3 jQuery.ajax

使用方法可以参考jQuery文档

3.3.1 封装优点
  • 支持更多形式的参数
  • 支持Promise
  • 支持的功能很多

注意:但现在更推荐使用axios

3.4 axios

是目前最新的AJAX库,采用了jQuery的封装思路。

3.4.1 示例
axios.get('/5.json')
  .then( response => 
      console.log(response)        
 )
3.4.2 aixos高级用法
  • JSON自动处理

  • axios如果发现响应的Content-Type是json

  • 就会自动调用JSON.parse

  • 请求拦截器

  • 可以在所有请求里加些东西,比如添加查询参数

  • 响应拦截器

  • 可以在所有响应中添加东西,甚至修改内容

  • 可以生成不同的实例(对象)

  • 不同实例可以设置不同配置,用于复杂场景

axios 使用参考文章:https://juejin.cn/post/6844903569745788941

4 注意

4.1 关于异步

1.如果 JS 不能直接拿到一个函数的结果,可以先去执行别的代码,等结果到了再取结果,这就是异步
2.异步的结果可以通过轮询获取,轮询就是定时去询问结果拿到了没有
3.异步的结果可以通过回调获取,一般来说结果会被作为回调的第一个参数
4.异步的好处是可以把用来等待的时间拿去做别的事情

4.2 关于回调

1.满足某些条件的函数才被称为回调,比如我写一个函数 A,传给另一个函数 B 调用,那么函数 A 就是回调
2.回调可以用于同步任务,不一定非要用于异步任务
3.有的时候回调还可以传给一个对象,如 request.onreadystatechange,等待浏览器来调用

4.3 关于Promise

1.Promise不是前端发明的,是目前前端解决异步问题的统一方案。
2.window.Promise 是一个全局函数,可以用来构造 Promise 对象
3.使用return new Promise((resolve, reject)=> {})就可以构造一个Promise对象
4.构造出来的Promise对象含有一个 .then()函数属性

4.3 关于return new Promise((resolve, reject)=>{…})中的resolve和reject

1.resolve 和 reject 可以改成任何其他名字,不影响使用,但一般就叫这两个名字。
2.任务成功的时候调用resolve,失败的时候调用reject
3.resolve和reject都只接收一个数据,而且this是空,不应该用this
4.resolve和reject并不是 .then(success, fail)里面的success和fail,resolve会去调用 success,reject会去调用fail

4.5 注意Promise不可取消

为了解决取消promise这个问题,axios自己想了个办法就是用CancleToken。
原理就是将请求编号,假设发了10个promise,其中9个不要了。就把id为1~9的promise对应的ajax请求终止。promise还是做,只不过ajax不要了。axios取消的不是promise而是请求。axios.CancleToken

部分资料参考来源:饥人谷


https://www.xamrdz.com/lan/5pw1996152.html

相关文章: