zoukankan      html  css  js  c++  java
  • 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的异步操作

      1、回调函数

        ajax典型的异步操作,利用XMLHttpRequest,回调函数获取服务器的数据传给前台  

        之前也分析过ajax(飞机票

        回调函数的含义就是耗时任务f1中执行f2,f1不会堵塞住,而是先执行f2,再延迟执行f1

      2、事件监听

        addEventListener

        当监听事件发生时,先执行回调函数,再对监听事件进行改写

      3、观察者模式,也叫订阅发布模式

        多个观察者可以订阅同一个主题,主题对象改变时,主题对象就会通知这个观察者

        其中步骤包括,订阅、发布、退订;先订阅(subscribe)一个主题对象,根据主题对象发布(publish)内容,期间也退订(unsubscribe)主题对象,一旦退订就无法再次发布

        可以把订阅一个主题对象理解成监听一个事件

        观察者模式的一个特点就是一旦主题事件一改变,就会通知整个观察者;观察者模式还可以计算出订阅事件的个数

      4、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){
                    var promise = new Promise(function(resolve,reject){
                    var xhr =  new XMLHttpRequest();
                    xhr.open("get",url);
                    xhr.onreadystatechange=ajax;
                    xhr.responseType = "json";
                    xhr.setRequestHeader("Accept", "application/json");
                    xhr.send();
                    function ajax(response){
                        if (this.readyState !=4) {
                            return;
                        }
                        if (this.status ==200) {
                                resolve(this.response)
                        }else{
                            reject(new Error(this.status.responseText))
                        }
                        
                    }
                })
                return promise;
            }
            getJSON("/new2").then(function(value){
                console.log(value);
            },function(error){
                console.log(error);
            })
       5、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 = () => {
            return getJSON()
                .then(data =>{
                    if(data.params){
                        return otherGetJSON(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 = await otherGetJSON(data);
                console.log(otherdata);
                return otherdata;
            }else{
                console.log(data)
                return data;
            }
        }
        6、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* 后面跟着一个可遍历的结构

     写在后面

        最近的review,让我对js又有新的认识,js异步操作是js的核心所在,也是js迷人的地方,async/await和generator都是promise的语法糖,我觉得没有优劣之分,可能道行太浅,还需刷道,希望业界前辈多多指责我,让我进步更快。

        好了,今天的交流就结束了,下次复习js定时器的内存分配等。

  • 相关阅读:
    积木游戏
    斐波那契公倍数
    莫比乌斯反演,狄利克雷卷积,杜教筛
    CF932E Team Work
    【算法学习/数据结构】李超树
    【算法笔记/数学内容】博弈论-从入土到入土
    瞎几把写的cspj题解
    【算法笔记】数位dp
    【算法笔记】树形dp
    攻防世界-WEB相关writeup-3
  • 原文地址:https://www.cnblogs.com/dirkhe/p/7384743.html
Copyright © 2011-2022 走看看