zoukankan      html  css  js  c++  java
  • JS高级-异步

    单线程

      只有一个线程,同一时间只能做一件事

      原因:避免DOM渲染的冲突

        浏览器需要渲染DOM

        JS可以修改DOM结果

        JS执行的时候,浏览器DOM渲染会暂停

        两段JS也不能同时执行(修改DOM就冲突)

        webworker支持多线程,但是不能访问DOM,本质JS还是单线程

      解决方案:异步

    case1

    {
        var i, sum = 0
        for(i = 0; i < 100000000; i++) {
            sum += i
        }
        console.log(sum)
    }

    case2

    {
        console.log(1)
        alert('a')
        console.log(2)
    }

    分析:JS执行阻塞DOM渲染,出现卡顿。因为js是单线程

    case3

    {
        console.log(100)
        setTimeout(function(){
            console.log(200)
        },100)
        console.log(300)
    }

    分析:JS是单线程的,第一行打印100,第二行setTimeout是异步,暂时不执行,先往下执行,第三行打印300,代码结束。然后发现setTimout没执行,那么打印200。

    event-loop

      事件轮询,JS实现异步的具体解决方案

      同步代码,直接执行

      异步函数先放在异步队列中

      待同步函数执行完毕,轮询执行异步队列的函数

    case1

    {
        console.log(100)
        setTimeout(function(){
            console.log(200)
        },100)
        console.log(300)
    }

    分析:同步代码,直接执行,第一行和第三行是同步代码,直接打印100和300,第二行是异步代码,先放入异步队列。同步代码执行完毕,这时候查看异步队列,执行setTimeout打印200

    case2

    {
        console.log(100)
        setTimeout(function(){
            console.log(200)
        },100)
        setTimeout(function(){
            console.log(300)
        })
        console.log(400)
    }

    分析:同步代码直接执行,第一行和第四行直接执行,打印100和400。

       同步代码执行完毕,查看异步队列。这时候有2个setTimeout函数,第三行会直接放入异步队列中,那么打印300。

       而第二行100ms之后才被放入异步队列中,打印200

    case3

    {
        $.ajax({
            url:'',
            success:function(result){
                console.log('a')
            }
        })
        setTimeout(function(){
            console.log('b')
        },100)
        setTimeout(function(){
            console.log('c')
        })
        console.log('d')
    }

    结果: d c a b或者 d c b a

    jQuery的Deferred

      dtd.resolve/dtd.reject

      dtd.then/dtd.done/dtd/fail

    case1

    function waitHandle() {
        var dtd = $.Deferred()
        !function(dtd){
            var task = function() {
                console.log('执行完毕')
                dtd.resolve()
            }
            setTimeout(task, 2000)
        }(dtd)
        return dtd
    }
    
    waitHandle()
        .then(function(){
            console.log('success')
        })

    case2

    function waitHandle() {
        var dtd = $.Deferred()
        !function(dtd){
            var task = function() {
                console.log('执行完毕')
                dtd.resolve()
            }
            setTimeout(task, 2000)
        }(dtd)
        return dtd.promise()
    }
    
    var w = waitHandle()
        $.when(w).then(function(){
            console.log('success')
        })

    注意:这2个case不同之处一个case是返回dtd还有一个返回dtd.promise()对象。

       第一个case w.reject()不会报错,但是会出现代码混乱

       第二个case w.reject()会报错,无法干预代码

    Promise

      回顾下语法

    case

    {
        function loadImg(src){
            return new Promise((resolve, reject)=>{
                let img = document.createElement('img')
    
                img.onload = () => resolve(img)
    
                img.onerror = () => reject()
    
                img.src = src
            })
        }
    
        const src = 'https://....jpeg'
    
        var res = loadImg(src)
        res.then(img => {
            console.log(img)
        }, () => {
            console.log('fail')
        })
    }

     异常捕获

      使用catch统一捕获异常

    case

    {
        function loadImg(src){
            return new Promise((resolve, reject)=>{
                let img = document.createElement('img')
                img.onload = () => resolve(img)
    
                img.onerror = () => reject('异常')
    
                img.src = src
            })
        }
    
        const src = 'https://....jpeg'
    
        var res = loadImg(src)
        res.then(img => {
            console.log(img)
        }).catch(e => {
            console.log(e)
        })
    }

    多个串联

      链式操作部分代码

    const res = loadImg(src)
        const res2 = loadImg(src2)
        res.then(() => {
            console.log('one')
            return res2
        }).then(() => {
            console.log('two')
        }).catch(e => {
            console.log(e)
        })

    Promise.all和Promise.race 

      Promise.all接收一个promise对象的数组,待全部完成之后,统一执行then

      Promise.race接收一个promise对象的数组,只要一个完成,就执行then

    async/await

      直接只用同步写法

    case

    {
        function loadImg(src){
            return new Promise((resolve, reject)=>{
                let img = document.createElement('img')
                img.onload = () => resolve(img)
    
                img.onerror = () => reject('异常')
    
                img.src = src
            })
        }
    
        const src = 'https://....jpeg'
        const src2 = 'https://...jpg'
        
        async function load() {
            const res = await loadImg(src)
            console.log(res)
            const res2 = await loadImg(src2)
            console.log(res2)
        }
        load()
    }

    虽然是同步写法,但是使用了Promise,并没有改变JS时单线程,异步的本质

  • 相关阅读:
    linux命令学习(3):ls命令
    敏捷开发 我的经验(三)运转
    敏捷开发 我的经验(二)资源计算-以人为本
    敏捷开发 我的经验(一)基本概念
    docker 搭建ntp服务器
    非程序员误入
    简单测试服务器磁盘读写速度
    搭建问题二之您添加的站点已存在
    搭建遇到问题一之安装fileinfo扩展插件失败
    简单快速搭建视频网站
  • 原文地址:https://www.cnblogs.com/sonwrain/p/10540416.html
Copyright © 2011-2022 走看看