异步与promise

111 阅读3分钟

回调函数

  • setTimeout()这个调用函数我们也称为回调函数callback
  • 普通函数按照代码顺序直接调用,而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数
  • 回调函数就是自己不调用,别人调用的函数

异步和回调的关系

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

如何区分同步异步

  • 如果一个函数的返回值处于以下三种内部,那么这个函数就是异步函数
  • setTimeout、AJAX(即XMLHttpRequest)、addEventListener

同步和异步

  • 同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
  • 异步:在等待这个任务结束时,同时处理其他的任务

同步任务和异步任务执行过程

  • 同步任务:都在主线程上执行,形成一个执行栈
  • 异步任务:1. 普通时间,如click、resize等;2. 资源加载,如load、error等;3. 定时器,包括setInterval、setTimeout等
  • js执行机制:先执行执行栈中的同步任务,异步任务(回调函数)放入任务队列中,一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行
  • 由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称事件循环(event loop)

promise的用法

  • promise指定回调函数的方式更加灵魂,旧的方式必须在启动异步任务前指定,promise:启动异步任务 - 返回promise对象 - 给promise对象棒的回调函数(甚至可以在底部任务结束后指定/多个)
  • promise支持链式回调,可以解决回调地狱问题,回调地狱是回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件,不便于阅读,不便于异常处理

第一步

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

第二步

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

用promise封装的ajax

ajax('get','/xxx')
    .then((response)=>{},(request)=>{})

使用promise调用需要改写ajax的封装源代码

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

我们封装的ajax的缺点

  • post无法上传数据,request.send(这里可以上传数据)
  • 不能设置请求头(request.setRequestHeader.(key,value)
  • 可以花时间把ajax写到完美,或者使用jQuery.ajax,或者使用比jquery更高逼格的axios

axios高级用法

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