最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 针要学前端 | JavaScript深度挖掘之异步编程

    正文概述 掘金(指针)   2021-01-02   365

    JavaScript异步编程

    0.先做题,醒醒脑子,成功的请直接跳转到参考,失败的按照顺序往下看

    console.log(1)
    setTimeout(()=> {
        console.log(2)
    }, 0)
    new Promise(res => {
        console.log(3)
        setTimeout(()=> {
            console.log(4)
            res()
        },0)
    }).then(()=> {
        console.log(5)
    })
    console.log(6)
    

    1.概念叨叨叨,让异步等一会儿

    众所周知JavaScript是单线程的,当初设计出来就是运行在浏览器上的脚本语言,浏览器最重要的操作就是Dom操作,而为了避免多个线程同时修改一个Dom,造成冲突,JavaScript就采用了单线程。

    优点:中华人民共和国46年,JavaScript上任浏览器,拿着喇叭大喊,我来浏览器就为三件事:安全!安全!还是TMD的安全!!!

    但是!!!剿匪需要时间,打黄老爷需要时间,老百姓还在等着呢!可惜了,咱兄弟一直是一起行动的(JS执行环境中负责执行代码的线程只有一个),现在耗时的事儿太多堵塞了呀。不过张麻子聪明啊,咱们兄弟这么多人分成俩队,一个叫同步模式队,一个叫异步模式队。不耗时的活比如贴大字报(console.log())由同步模式队做,耗时的比如赴宴、喝酒、调兵(延时,ajax)就让异步模式队干。等同步模式队干完了,异步模式队再按照时间长短把活儿给干了,先剿匪,再杀黄四郎,咱一定还浏览器一个朗朗乾坤。

    “大哥,异步还没做,在排队”。

    “不急,让异步等一会儿!”

    2.同步模式

    3.异步模式

    先说俩概念

    整个过程就是,先分任务,同步任务在主线程开始执行,异步任务到任务队列去按照耗时排队,等同步任务做完了,就开始矮个子里拔高个,挨个去将异步任务推入主线程去执行。如此循环往复,子子孙孙,无穷匮也~

    想看动态图的,可以看看这个老哥这里

    异步操作的常见语法

    3.1 事件监听
    document.addEventListener('click', function() {
        
    })
    
    3.2 回调函数

    相信大家看到回调函数,第一时间想到的就是回调地狱,别怕,这是多么优美的冲锋啊?(联系侵删) 针要学前端 | JavaScript深度挖掘之异步编程

    3.2 promise

    二话不说,先用起来!

    // Promise是一个对象,接受一个函数作为参数
    // 这个函数接受两个参数,一个resolve 成功回调,一个reject 失败回调
    // 一个promise只能在成功或失败中保持一个状态,且不可更改
    // 成功回调在.then中触发,失败回调在.catch中触发
    let p = new Promise((resolve, reject) => {
        // 使用定时器模拟接口调用
        setTimeout(()=> {
            let randonNum = Math.random()
            if( randonNum > 0.5) {
                resolve(randonNum)
            } else {
                reject(randonNum)
            }
        }, 1000)
    })
    
    p.then((value) => {
        console.log(value)
    }).catch((value) => {
        console.log(value)
    })
    

    当然,Promise的链式调用才是解决回调地狱的秘密武器

    let count = 1
    // 每次调用,count++
    let promiseAjax = function () {
        return new Promise((res, rej) => {
            setTimeout(()=> {
                count++
                res(count)
            }, 1000 * count)
        })
    }
    let p = promiseAjax()
    p.then(value => {
        console.log(value)
        return promiseAjax()
    }).then(value => {
        console.log(value)
        return promiseAjax()
    }).then(value => {
        console.log(value)
        return promiseAjax()
    }).then(value => {
        console.log(value)
        return promiseAjax()
    })
    

    Promise的静态函数中,有四个可以记一下

    • Promise.all([]) 接受一堆Promise,并行处理,全部成功才成功,返回一个新的Promise
    • Promise.race([]) 也是接受一堆Promise,看谁跑得快,谁快就用谁的,一个结束,就结束,可以用于接口超时处理
    • Promise.resolve() 返回一个状态由给定value决定的Promise对象。如果该值是thenable(即,带有then方法的对象),返回的Promise对象的最终状态由then方法执行决定;否则的话(该value为空,基本类型或者不带then方法的对象),返回的Promise对象状态为fulfilled,并且将该value传递给对应的then方法。通常而言,如果您不知道一个值是否是Promise对象,使用Promise.resolve(value) 来返回一个Promise对象,这样就能将该value以Promise对象形式使用。
    • Promise.reject() 返回一个状态为失败的Promise对象,并将给定的失败信息传递给对应的处理方法

    宏任务与微任务

    同为异步,也分两种,这就是宏任务(macrotask )与微任务(microtask )

    别的不谈,有微任务先执行微任务,再执行宏任务,所以,现在上面的面试题会做了吗?

    3.4 generator

    Promise的链式调用,你链多了,看着也膈应,所以es6中还有一个生成器函数(generator)

    generator是一个可以“返回”多次的“函数”,这样就可以保存每一次的值

    二话不说,先用起来

    function * foo () {
        console.log("start")
        let r1 = yield promiseAjax()
        console.log(r1)
        let r2 = yield promiseAjax()
        console.log(r2)
    }
    // foo并不会执行,只会生成一个generator对象
    // 需要调用g的next方法,函数才会向下执行,并且执行到yield处停止
    // g.next()返回一个对象 {value: x, done: true/false},其中value是Promise reuturn的值
    // done代表着generator的执行状态,true表示执行结束,false表示没有执行结束
    // yield只会暂停函数执行,并不是return出去,当下一次next方法执行时,函数又会接着往下执行
    let g = foo()
    console.log(g)
    let result = g.next()
    result.value.then(data => {
        // 将data赋值给r1,并且开始下一次执行,执行到下一个yield
        g.next(data)
    })
    

    generator函数的执行吧,如果你想执行到底,你得一直next()下去,但是这样一直写太呆了,我们给它封装成一个递归函数

    function co (generator) {
        let g = generator()
        function handleResult (result) {
            if (result.done) return
            result.value.then(data => {
                handleResult(g.next(data))
            })
        }
        handleResult(g.next())
    }
    

    3.5 async/await

    是不是觉得generator写的方式很蛋疼?没关系,之前蛋疼并且爱动脑子的家伙已经为我们准备好了generator的语法糖,用法极其简单,写法也是同步的写法,堪称完美

    async function foo () {
        let r1 = await asyncFn1()
        let r2 = await asyncFn2()
        let r3 = await asyncFn3()
        console.log(r3)
    }
    

    参考


    起源地下载网 » 针要学前端 | JavaScript深度挖掘之异步编程

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元