异步 与 Promise

76 阅读3分钟

一、异步、同步、回调

同步

  1. 如果能直接拿到结果,那就是同步
  • 比如你在医院挂号,你拿到号才会离开窗口,同步任务可能消耗 10 毫秒,也可能需要 3 秒,总之不拿到结果你是不会离开的

异步

  1. 如果不能直接拿到结果,那就是异步
  • 比如你在餐厅门口等位,你拿到号可以去逛街,什么时候才能真正吃饭呢?
  • 你可以每10分钟去餐厅问一下(轮询)
  • 你也可以扫码用微信接收通知(回调)

回调 (callback)

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

异步和回调的关系

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

判断同步异步

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

二、如果异步任务有两个结果,成功或失败

  1. 方法一:回调接受两个参数
fs.readFile('./1.txt', (error, data)=>{
  if(error){ console.log('失败'); return }
  console.log(data.toString()) // 成功
})
  1. 方法二:搞两个回调
ajax('get','/1.json', data=>{}, error=>{})
// 前面函数是成功回调,后面函数是失败回调
ajax('get', '/1.json', {
  success: ()=>{}, fail: ()=>{} 
})
// 接受一个对象,对象有两个 key 表示成功和失败
  1. 这些方法的不足
  • 不管方法一还是方法二,都有问题
  • 不规范,名称五花八门,有人用 success + error,有人用 success + fail,有人用 done + fail,
  • 容易出现回调地狱,代码变得看不懂
  • 很难进行错误处理
  1. 改进方法: 使用promise return new Promise((resolve, reject)=>{})
第一步
return new Promise((resolve,reject)=>{...})
任务成功则调用 resolve(result)
任务失败则调用 reject(error)
resolve 和 reject 会再去调用成功和失败函数

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

三、axios

  1. 目前最新的 AJAX 库
代码示例
axios.get('/5.json')
  .then( response =>
    console.log(response)
  )

axios 高级用法

  1. JSON 自动处理
  • axios 如果发现响应的 Content-Type 是 json就会自动调用 JSON.parse
  1. 请求拦截器
  • 你可以在所有请求里加些东西,比如加查询参数
  1. 响应拦截器
  • 你可以在所有响应里加些东西,甚至改内容
  1. 可以生成不同实例(对象)
  • 不同的实例可以设置不同的配置,用于复杂场景