异步与Promise

异步

能直接拿到结果(等待结果出现)

不能直接拿到结果(先运行别的,然后等结果到了被通知)

  • 每过一段时间问一下(轮询)
  • 通过微信扫码接受通知(回调)

异步举例

  以ajax为例

  1. requeset.send()之后,并不能直接得到response
  2. 不信console.log(request.response)试试
  3. 必须等到readyState变为4以后,浏览器回头调用request。onreadystatechange函数
  4. 我们才能得到request.response
  5. 这跟餐厅给你发微信提示的过程是类似的

  回调callback

  1. 你写给自己用的函数,不是回调
  2. 你写给别人用的函数,才是回调
  3. request.onreadystatechange就是我写给浏览器调用的
  4. 意思是你(浏览器)回头(将来)调用一下这个函数,不是马上调用

回调

写了却不调用,给别人调用的函数,就是回调

【回头你调用一下呗】

意会

回调举例

把函数1给另一个函数2

function f1(str){
  console.log(str)  
}
function f2(fn){
  fn('你好我是来自f1的代码') 
//此处的参数对应f1(str) } f2(f1)

  分析

  1. 我调用f1没有? 答:没有调用
  2. 我把f1传给f2(别人)了 没有?答:传了
  3. f2调用f1了没有?答:f2调用了f1

那么,f1是不是我写给f2调用的函数?答:是

所以,f1是回调

异步和回调的关系

关联

  • 异步任务需要在得到结果时通知js来拿结果
  • 怎么通知呢?
  • 可以让js写一个函数地址(电话号码)给浏览器
  • 异步任务完成时浏览器调用该函数地址即可(拨打电话)
  • 同时把结果作为参数传给该函数(电话里通知)
  • 这个函数是我写给浏览器调用的,所以是回调函数

区别

  • 异步任务需要用到回调函数来通知结果
  • 但回调函数不一定只用在异步任务里
  • 回调可以用到同步任务里
  • array.forEach(n=>console.log(n))就是同步回调

函数为同步还是异步?通过文档或者特征

 

判断同步异步

如果一个函数的返回值处于

  1. setTimeout
  2. AJAX(即XMLHttpRequest)
  3. AddEventListener
  4. 这三个东西内部,那么这个函数就是异步函数

ajax可以设置为同步,但是体验会很差,别去做。

 

简化箭头函数

由于f1声明之后只用了一次,所以可以删掉f1

function f1(x){ console.log(x)}
摇骰子(f1)
//改为如下
摇骰子(x=>{console.log(x)}
//再简化
摇骰子(console.log)
//但是一定要注意,参数个数必须一致

 

总结  

  • 异步任务不能拿到结果
  • 浴室我们传了一个回调给异步任务
  • 异步任务完成时调用回调
  • 调用的时候把结果作为参数
  • 希望你已经理解上面过程

 

 一定要避免回调地狱,可读性和可维护性都很差。

 

怎么解决回调问题

  有什么办法解决这三个问题

  • 规范回调的名字和顺序
  • 拒绝回调地狱,让代码可读性更强
  • 很方便得捕获错误

  根据前人经验提出的promise思想

用promise封装ajax

ajax = (method,url,options)=>{
    const {success,fail} = options//析构赋值
    const request = new XMLHttpsRequest()
    request.open(method,url)
    request.onreadystatechange = ()=>{
        if(request.readyState === 4){
//成功就调用resolve,失败就调用reject success.call(null,request.response) }else if (request.status >= 400){ fail.call(null,request,request.status) } } } request.send() } //调用 ajax('get','/xxx',{ success(response){},fail:(request,status)=>{ }) //左边是function缩写,右边是箭头函数,记下来

  上面的代码比较傻,没用promise写

ajax = (method,url,options)=>{
   return new Promise((resolve,reject)=>{      
    const {success,fail} = options//析构赋值
    const request = new XMLHttpsRequest()
    request.open(method,url)
    request.onreadystatechange = ()=>{
        if(request.readyState === 4){
//成功就调用resolve,失败就调用reject
          success.call(null,request.response)  
    }else if (request.status >= 400){
          fail.call(null,request,request.status)  
        }  
      } 
    }
     request.send()
 })
}

  return new Promise((resolve,reject)=>{})

  背下这五个单词即可,用熟再说

小结

  第一步

  1. return new Promise((resolve,reject)=>{})
  2. 任务的成功则调用resolve(result)
  3. 任务失败则调用reject(error)
  4. resolve和reject会再去调用成功和失败的函数

  第二步

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

  点到为止

  •   先讲到这里,promise还有高级用法,以后再说

封装的ajax的缺点

  • post无法上传数据
  • 不能设置请求头
  • 解决方案 1、花时间写到完美 2、使用jQuery.ajax 3、使用axios这个很实用
posted @ 2021-01-13 20:31  时间观测者  阅读(41)  评论(0编辑  收藏  举报