前端JS进阶六(异步)

2018-09-03  本文已影响0人  EmilioWeng

单线程

// 循环运行期间,JS执行和DOM渲染暂时卡顿
  var i,sum = 0;
  for(i=0;i<10000000;i++){
    sum += i;
  }
  console.log(sum);
// alert不处理,JS执行和DOM渲染暂时卡顿
  console.log(1)
  alert('hello')
  console.log(2)

避免DOM渲染冲突

  console.log(100)
  setTimeout(function(){
    console.log(200)   //1000ms之后执行
  },1000)              //1000ms后再进入异步队列,先让其他JS代码执行
  console.log(300)
  console.log(400)
// 100 300 400 200

  console.log(100)
  $.ajax({
    url:'xxxx',
    sucess:function(result){  //ajax加载完才执行
      console.log(result)     //ajax后再进入异步队列,先让其他JS代码执行
    }
  })
  console.log(300)
  console.log(400)
// 100 300 400 result

异步存在的问题

事件轮询 event-loop

  setTimeout(function(){
    console.log(1)
  },)
  setTimeout(function(){
    console.log(2)
  },100)
  console.log(3)

//主进程
  console,log(3)

//异步队列
  //立即被放入异步队列
  function(){  
    console.log(1)
  })
  //100ms后这个函数会被放入异步队列
  function(){  
    console.log(2)
  })

jQuery-deferred

//jQuery1.5之前
  var ajax = $.ajax({
    url:'data.json',
    success:function(){
      console.log('success1')
      console.log('success2')
      console.log('success3')
    },
    error:function(){
      console.log('error')
    }
  })
  console.log(ajax) // 返回一个XHR对象

//jQuery1.5之后
  //1 .done.fail写法
  var ajax = $.ajax('data,json')
  ajax.done(function(){
    console,log('success1')
  }).fail(function(){
    console,log('error')
  }).done(function(){
    console,log('success2')
  })
  console.log(ajax) // 返回一个deferred对象

  //2 .then写法 很像Promise的写法
  var ajax = $.ajax('data.json')
  ajax.then(function(){
    console.log('success1')
  },function(){
    console.log('error1')
  }
  .then(function(){
    console.log('success2')
  },function(){
    console.log('error2')
  }

jQuery1.5之后带来的变化

使用jQuery Deferred

//给出一段简单异步代码,使用setTimeout函数
  var wait = function(){
    var task = function(){
      console.log('执行完成')
    }
    setTimeout(task,2000)
  }
  wait()

//使用jQuery Deferred
  function waitHandle(){
    var dtd = $.Deferred() //创建一个deferred对象

    var wait = function(dtd){ //要求传入一个deferred对象
      var task = function(){
        console.log('执行完成')
        dtd.resolve() //表示异步队列已经完成
        //dtd.reject()  //表示异步任务失败或者出错
      }
      setTimeout(task,1000)
      return dtd  //要求返回deferred对象
    }
    //注意这里一定要有返回值
    return wait(dtd)
    }

  var w = waitHandle()
  w.then(function(){
    console.log('ok 1')
  },function(){
    console.log('err 1')
  })
  w.then(function(){
    console.log('ok 2')
  },function(){
    console.log('err 2')
  })
  // 也可以使用 w.done w.fail

使用dtd.promise()

  function waitHandle(){
    var dtd = $.Deferred()
    var wait = function(dtd){
      var task = function(){
        console.log('执行完成')
        dtd.resolve()
        //dtd.reject()
      }
      setTimeout(task,1000)
      return dtd.promise()  //注意 这里返回promise而不是返回deferred对象
    }
    return wait(dtd)
    }

 var w = waitHandle() //经过上面的修改 这里的w是promise对象
  $.when(w)
  .then(function(){
    console.log('ok 1')
  })
  .then(function(){
    console.log('ok 2')
  })
  //注意 这里执行w.reject()会报错
  //函数内部封装的时候可以使用resolve reject 函数外部使用时只能用then done fail被动监听了

总结

Promise

promise语法见之前的文章:https://www.jianshu.com/p/54c7c55677f7

  function loadImg(src){
      const promise = new Promise (function (resolve,reject){
          var img = document.createElement('img')
          img.onload = function(){
              resolve(img)
          }
          img.onerror = function(){
              reject()
          }
          img.src = src
      })
      return promise
  }

  var src = 'https://www.imooc.com/static/img/index/logo_new.png'
  var result = loadImg(src)
  result.then(function(img){
      console.log(img.width)
  },function(){
      console.log('failed')
  })
  result.then(function(img){
      console.log(img.height)
  },function(){
      console.log('failed')
  })

Promise异常捕获

catch不仅能捕获程序逻辑语法的报错,还能捕获reject()返回的报错

//规定then只接收一个成功的参数,最后统一用catch捕获异常
  result.then(function (img){
    console.log(img.width)
  }).then(function (img){
    console.log(img.height)
  }).catch(function (ex){
    console.log(ex)  //统一用catch捕获异常
  })

Promise多个串联

我们要求程序的图片按顺序加载,先加载图片1,再加载图片2

  var src1 = 'https://www.baidu.com/static/img/index/logo1.png'
  var result1 = loadImg(src1)
  var src2 = 'https://www.baidu.com/static/img/index/logo2.png'
  var result2 = loadImg(src2)
  //链式操作
  result1.then(function (img){
    console.log('图片1加载完毕')
    return result2  //一定要return result2!!! 非常重要!
  }).then(function (img){
    console.log('图片2加载完毕')
  }).catch(function (ex){
    console.log(ex)  //统一用catch捕获异常
  })

Promise.all和Promise.race

//Promise.all接收一个Promise对象的数组
  //待全部完成之后,统一执行success
  Promise.all([result1,result2]).then(datas=>{
    //接收到的datas是一个数组,依次包含了多个promise返回的内容
    console.log(datas[0])
    console.log(datas[1])
  }) 

//Promise.race接收一个Promise对象的数组
  //只要有一个完成,就执行success
  Promise.race([result1,result2]).then(datas=>{
    //接收到的data即最先完成的promise的返回值
    console.log(datas[data])
  }) 

Promise状态

Promise的then

async/await (ES7中的标准)

  const load = async function(){
    const result1 = await loadImg(src1)
    console.log(result1)
    const result2 = await loadImg(src2)
    console.log(result2)
  }
  load()

用法

特点

上一篇 下一篇

猜你喜欢

热点阅读