JS高级-异步

Posted 苏荷酒吧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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时单线程,异步的本质

 

以上是关于JS高级-异步的主要内容,如果未能解决你的问题,请参考以下文章

JS高级——await-async

JS高级——await-async

react高级特性

JS高级-异步

在Nuxt.js组件中获取异步数据

es6常用功能与异步详解(JS高级面试题)