【 JS进阶 ]】分析JS中的异步操做

  JS由于是单线程的,因此在执行事务的时候,每每会由于某个事务的延迟,而致使服务器假死,这时候异步编程就显的格外重要,可是异步编程通常理解为回调函数callback,典型的就是node,回调函数的层层嵌套又致使程序过于冗余,由于闭包的存在,致使了内存的泄露或者误改上一层回调函数的参数,因而又有一个疑问,能不能用同步的方式去写异步,ES6的promise就是以同步流程的方式写出异步操作,可是piomise原生操做写起来比较长,能不能简介操做promise,ES7就又出现async/await的概念,与async/await同等语法糖做用的有依赖co库的generator函数,generator函数也是用来解决异步操做,不过得依赖co库, co 函数库是著名程序员 TJ Holowaychuk 于2013年6月发布的一个小工具,用于generator函数的自动执行。
  好了,那就罗列出js的异步操做
  一、回调函数

 

    ajax典型的异步操做,利用XMLHttpRequest,回调函数获取服务器的数据传给前台  
    以前也分析过ajax( 飞机票
    回调函数的含义就是耗时任务f1中执行f2,f1不会堵塞住,而是先执行f2,再延迟执行f1
  二、事件监听

 

    addEventListener
    当监听事件发生时,先执行回调函数,再对监听事件进行改写
  三、观察者模式,也叫订阅发布模式

 

    多个观察者能够订阅同一个主题,主题对象改变时,主题对象就会通知这个观察者
    其中步骤包括,订阅、发布、退订;先订阅(subscribe)一个主题对象,根据主题对象发布(publish)内容,期间也退订(unsubscribe)主题对象,一旦退订就没法再次发布
    能够把订阅一个主题对象理解成监听一个事件
    观察者模式的一个特色就是一旦主题事件一改变,就会通知整个观察者;观察者模式还能够计算出订阅事件的个数
  四、promise

 

    上面也提到了,promise是异步编程的解决方案,是一种容器,保存着异步操做的结果,能够把异步函数以同步函数的形式写出来
    promise第一个特色:对象状态不受外界影响,有三个状态pending(),fulfilled(),rejected(),只有异步操做才会更改这个状态,其余操做没法改变这个状态
    promise第二个特色:一旦状态改变,pending->fulfilled或pending->rejected,状态就会凝固住,称为resolve,经过promise的回调函数能够当即获得这个结果,与事件监听不一样,一旦事件错误,就没法再次监听
    promise第三个特色:避免了回调函数的层层嵌套,实际上写promise时,虽然没有回到函数的层层嵌套,可是又有then的嵌套,这个又有新的解决方法
    promise第一个缺点:一旦promise创建,就会当即执行,没法中途中止
      举个例子,假如去淘宝买东西,去看上一个东西,想要买,已经点击肯定购买了,可是你又cancle了,忽然你发现工资发了,你又发送一个请求说又要买了,服务器接收到了你的第一个异步请求,你又有异步请求,异步请求又不能中止,求服务器阴影面积?
    promise的第二个缺点:promise不设置回调函数,抛出的错误没法在外部捕获
    piomise的第三个缺点:处于pending状态,没法知道进展到哪一个状态
    下面一个经典的案例:用promise写出ajax,就体现了promise的特色

 

             function getJSON(url){
                varpromise = new Promise(function(resolve,reject){
                var xhr=  newXMLHttpRequest();
                xhr.open("get",url);
                xhr.onreadystatechange=ajax;
                xhr.responseType ="json";
                xhr.setRequestHeader("Accept","application/json");
                xhr.send();
                functionajax(response){
                    if (this.readyState !=4) {
                        return;
                    }
                    if (this.status ==200) {
                            resolve(this.response)
                    }else{
                        reject(new Error(this.status.responseText))
                    }
                  
                }
            })
            returnpromise;
        }
        getJSON("/new2").then(function(value){
            console.log(value);
        },function(error){
            console.log(error);
        })

 

 
   五、es7语法糖async/await

 

     async异步函数是promise的完成状态,async函数直接then去获取状态改变值,catch来获取错误
     await只容许在async内部使用,就是async异步函数内部想要继续then,就能够采用await异步函数,await异步函数是内部的async异步函数
       async极大精简了promise的操做   
async  function asyncFn(){
        return 123;
    }
    asyncFn()
        .then(x => {console.log(x)})
        .catch(err=> console.log(error))

 

    这是未精简的promise操做,功能是把最终结果return最外层的promise,可是 用到了多层嵌套,比较复杂

 

    const fn = () => {
        returngetJSON()
            .then(data =>{
                if(data.params){
                    returnotherGetJSON(data).then(otherdata =>{
                        console.log(otherdata);
                        return otherdata;
                    })
                }else{
                    console.log(data)
                }
            })
    }

 

    而async异步函数,直接去return出结果就行,这就是await是async内部async异步函数

 

    const fn = async () => {
        const data = await getJSON();
        if(data.params){
            const otherdata = awaitotherGetJSON(data);
            console.log(otherdata);
            returnotherdata;
        }else{
            console.log(data)
            return data;
        }
    }

 

    六、co库的generator函数

 

      generator函数是一个异步函数,只有异步操做有结果才会交还执行权
      generator用到了ES6的遍历Iterator的概念,建立一个指针对象,指向数据结构的起始位置,每次next指向下一个指针结构成员,直至指向的下一个结构成员为undefined
      generator概念就是,每次遍历读用next方法,内部指针从结构头部指向下一个结构成员,直至下一个结构成员为undefined,遇到yield或return时会返回value和done参数,value表示yield或return的值,done表示是否结束 

 

function * gen(x){
      var y = yield x +2;  
   
      return y;
}
var g = gen(1);
console.log(g.next())// { value: 3, done: false }
console.log(g.next())// { value: undefined, done: true }

 

      yield是遍历的中止标志
      而generator中的yield*表示 yield* 后面跟着一个可遍历的结构
须要了解web前端的同窗,+群434/6239/99
相关文章
相关标签/搜索