异步

2020-12-18 10:29发布

什么是单线程 和异步有什么关系
单线程 只有一个线程 同一时间只能做一件事情 原因是为了避免DOM渲染的冲突 解决方案就是异步
浏览器需要渲染DOM js可以修改DOM 所以js执行的时候 浏览器DOM 渲染会暂停 两段js也不能同时执行(如果都修改DOM都冲突了)
webworker 支持多线程 但是不能访问DOM
异步问题1 没按照书写方式顺序执行 可读性差 2.callback函数不容易模块化

什么是event-loop js原生的解决异步的方法 又叫事件轮巡机制
例如 console.log(1), setTimeout(()=>{console.log(2)},1000),以及一个ajax{success()=>{console.log(3)}} 以上三个打印 肯定是先打印1 因为其是在主线程中的事件 肯定是先被执行的 然后第二个是主线程执行完之后过1秒然后把其放在异步进程中 事件轮巡机制在主线程程序执行完之后就相当于一直监视异步进程 发现里面有东西就把他提到主线程之中执行 其中ajax是根据网速的快慢从而放进异步进程中的 所以不能确定2和3到底是谁先打印 如果网速快 ajax不到一秒就返回了 那肯定是3先打印如果大于一秒就是2先打印

是否用过jqery 的 deferred //jqery的异步的解决方法
1.5之前jqery的请求返回xml对象 之后返回deferred对象
promise就是deferred过度的 jqery1.5已经有ajax.then().then().file()
虽然不管用什么方式 也无法改变js异步和单线程的本质 但是可以从写法上杜绝callback这种形式 因为在一个ajax里面写三个内嵌回调 总比不上三个.then()链式调用 它是一种语法糖形式 但是解耦了代码 很好的体现了开放封闭原则 开放封闭原则就是对扩展开放 对修改封闭
举例就是如果用callback形式的回调如果里面有三个内嵌回调 要加第四个 那就相当于修改了原来的主代码因为要在他的代码里再内嵌一个 只能一直往里面修改 在外扩展不了 但是用.then()的方式就不一样的 用.then()的方式如果再加一个回调不修改源代码 但是扩展了源代码
23种事件模式 5个设计原则要了解后者要先于前者学习

Promise的基本使用和原理
首先定义一个函数 穿进去一个参数
function loadImg(src){
定义一个变量初始化一个promise实例 最终返回一个promise实例 要接收一个函数 函数里面有两个参数 resolve reject 这是大概步骤 其余的就是在promise函数里面写的逻辑了
var 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= ‘’
var result = loadimg(src)
result .then(function(img)}{
console.log(1,img.width)
return img
},funtion(){
console.log(‘error 1’)
}).then(function(img){
console.log(2,img.height)
})
还可以统一捕获异常代码 就是.then().then不管有多少个 在最后写个.catch(穿个形参)就行
多个串联 一个图片加载完加载第二个
promise.all 和 promise.race的区别是穿进去的数组里面的所有的都执行完了才执行下一步 而promise.race是谁先执行完就执行下一步
promise标准-状态变化
pending 例如一个图片穿进去 没开始加载就是pending
fulfilled 成功 rejected 失败
状态变化之间不可逆 也不可变
.then里面得return一个promise实例 如果没有 那就反回的是.then执行的promise实例
示例代码如下

 ```
  //封装一个promise
getNumber(){
  let p = new Promise((resolve,reject)=>{
    setTimeout(()=>{
      let num = Math.ceil(Math.random()*10)
      if(num<5){
        resolve(num)
      }else{
        reject('数字大了')
      }
    },2000)
  })
  return p
},
toggle: function() {//这是一个点击方法
  this.getNumber().then(res=>{
    console.log(res)
    return res+1//返回一个以供下个then用 如果想要获得一个异步执行结果后执行下个异步代码 那就在这里面返回第二个一步函数的调用
  },err=>{
    console.log('没异常的错误'+err)
    // return err
  }).then(res=>{console.log('第二层'+res)
    return res+1
  },err=>{
    console.log('米异常第二层'+err)
  }
  ).then(res=>{console.log('第三层'+res)})

 ```


 如果想要在一个回调之后调第二个异步回调
 ```
  //封装一个promise
getNumber(){
  let p = new Promise((resolve,reject)=>{
    setTimeout(()=>{
      let num = Math.ceil(Math.random()*10)
      if(num<5){
        resolve(num)
      }else{
        reject('数字大了')
      }
    },2000)
  })
  return p
},
//第二个回调
two(){
  let t = new Promise((resolve,reject)=>{
    setTimeout(()=>{
      let num = Math.ceil(Math.random()*100)
       if(num<50){
        resolve(num)
      }else{
        reject('数字大了')
      }
    },1000)
  })
  return t
},
toggle: function() {//这是一个点击方法
  this.getNumber().then(res=>{
    console.log(res) //如果想要在第一个回调结束后调用第二个回调就可以用这种方法 但是一定要在第一个回调底部return 出去第二个回调 如果想要第一个回调失败调用就得走.then中的err了
    return this.two()
  },err=>{
    console.log('没异常的错误'+err)
    // return err
  }).then(res=>{console.log('第二层'+res)
    return res+1
  },err=>{
    console.log('米异常第二层'+err)
  }
  ).then(res=>{console.log('第三层'+res)})

 ```


 promise中的 all 与 race的用法 但是all需要全部为正确返回才可以返回这点要注意
 ```
  //封装一个promise
getNumber(){
  let p = new Promise((resolve,reject)=>{
    setTimeout(()=>{
      let num = Math.ceil(Math.random()*10)
      if(num<5){
        resolve(num)
      }else{
        reject('数字大了')
      }
    },2000)
  })
  return p
},
//第二个回调
two(){
  let t = new Promise((resolve,reject)=>{
    setTimeout(()=>{
      let num = Math.ceil(Math.random()*100)
       if(num<50){
        resolve(num)
      }else{
        reject('数字大了')
      }
    },1000)
  })
  return t
},
toggle: function() {//这是一个点击方法
  Promise.all([this.getNumber(),this.two()]).then(results=>{console.log(results)})
 ```
 rece也是一样的写法 不过race是返回最先执行完的数
 Promise 充分执行了六大设计模式原则之中最重要的开放封闭原则 用第一个回调调第二个回调的时候不在第一个回调里面写臃肿的代码 对扩展开放 对内部修改封闭123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114

async/await和Promise的区别 联系
await后面是跟一个promise实例



作者:前端阿龙

链接:https://blog.csdn.net/weixin_42790916/article/details/84845058

来源:CSDN
著作权归作者所有,转载请联系作者获得授权,切勿私自转载。