温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

JavaScript异步怎么理解

发布时间:2022-03-25 11:07:47 来源:亿速云 阅读:281 作者:iii 栏目:web开发

本篇内容主要讲解“JavaScript异步怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript异步怎么理解”吧!

导读

首先,要知道JavaScript是一门单线程的语言,要搞明白其为何会设计成单线程,要先来说一下JavaScript的最初应用场景。

其次,在单线程语言中如何处理多线程的任务。

再次,同步和异步的流程以及如何理解异步。

然后,在解决复杂的逻辑业务时,出现了什么样的问题。

再然后,怎样解决这一问题。

=> Promise/.then(),async/await,

最后谈谈微任务及宏任务

JavaScript最初的应用场景

最初,JavaScript的设计是作为浏览器脚本语言实现用户的交互,而为了避免多线程给我们带来很多不必要的麻烦,比如说:一个线程在删除一个节点,而另一个线程在修改这个节点,这时我们应该以哪一条线程为主呢?

因此,设计者将其设计成单线程的语言。

在H5中规定了JS可以拥有多个子线程,但是子线程仍然是依托于主线程的,且不能够操作节点。

为什么要使用多线程

单线程的缺点:

单线程有一个“致命”的缺点,就是会造成阻塞;

因为是单线程,所以在程序运行时是按照先进先出的原则来进行任务处理的,也正是因如此,在主线程遇到了耗时操作后,其后的任务就进入到了等待的状态。如果此时CPU是被占用的,也没什么,但是如果这个耗时任务是一个不占CPU的操作,举个栗子:向服务端请求数据。这个时候CPU出入空闲状态但是程序并没有执行结束,这就形成了阻塞。

启发:

在进行耗时操作且影响代码正常运行时,我们可以先不管这个操作,将其挂起。先处理后面的任务,等到主线程清空时,再来执行这个任务。于是出现了同步任务和异步任务。

同步和异步及程序运行流程

关于这一块内容,笔者建议从整体来看,将这一块中的内容结合起来读,可能会更好理解

我们可以将同步任务理解为在主线程中执行的任务,异步任务理解为在子线程执行。

同步任务和异步任务的执行过程:

同步任务正常运行,没有特殊情况会一直执行完毕;

当主线程运行到异步任务时,会安排一个子线程去运行异步任务,当异步任务运行结束后,向任务队列发送一个事件。表示该异步任务可以进入主线程执行了。

当不考虑下面讲的微任务和宏任务时,我们的程序运行时,会先执行同步任务,执行到异步任务后,将其发送到子线程中运行,运行结束会向任务队列发送一个事件。同步任务执行完毕即主线程清空后,主线程会向任务队列询问,是否有接收到事件,如果没有,那么主线程会一直询问,这个过程称为event loop;如果有,就执行这个事件。直到程序全部完成。

事件

在上文我们提到了事件这一概念,可以将事件理解为异步任务返回的一个回调函数,这个回调函数也就是事件会在主线程上运行。异步任务必须有回调函数。

拓展:异步函数必须return一个Promise对象

关于事件,阮一峰前辈是这么写的:

"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。

“回调地狱”

在实际开发中,为了实现一些逻辑需求,可能会用到多层回调函数嵌套。这个时候会导致代码的可读性很差。人们称之为“回调地狱”

Promise对象

代表的是异步操作 最终完成或失败

目的:将回调函数的多层嵌套形式,拆解成链式调用的形式。

本质:函数返回的对象,在这个对象上绑定回调函数,避免从一开始将回调函数作为参数传入上一层函数。

一个Promise必然会处于这几种状态:

待定(pending):初始状态,既没有被兑现,也没有被拒绝

已兑现(fulfilled):意味着操作成功完成 resolve

已拒绝(rejected):意味着操作失败 reject

Promise的使用:一般作为函数的返回值

const fn = function(){

    return new Promise((resolve,reject)=>{

        if(ture){

            resolve(a);

        }else{

            reject(b);

        }

    })

}

fn()

    .then((res)=>{有返回值的函数})

    .then((res)=>{有返回值的函数})

    .then((res)=>{有返回值的函数})

    …

    .then(res=>{最后的函数})

// 如果Promise对象中的请求完成了,那么将resolve的值传给then中的回调函数作为参数执行then方法

// 可以附加 .catch()在链式结构的末尾,来捕获错误(reject传回的值),并且之后的then不会执行

// 可以在最后加一个 .finally() 来执行清理操作  并且这个方法不管请求成功与否都会执行

async/await

是Promise的语法糖;让繁琐的then(),和冗长的链式调用可读性变得更长些;

具体使用方式:

//异步函数1

function getData(data){  

    return new Promise((reslove)=>{

        reslove(data)

    })

}

//异步函数2

function sayHello(data){

    return new Promise((reslove)=>{

        reslove(data)

    })

}

//异步函数 

async function fn(){

     // await相当于。then()    getData()相当于是回调函数

    // await必须在async修饰的函数体内使用

    const promiseA = await getData('info')

    const promiseB = await sayHello(promiseA);

    console.log(promiseB)

}

谈谈微任务和宏任务

微任务

注意:Promise对象中的代码是同步的,then()方法中的回调函数才是异步的

then()中的是微任务

宏任务

定时器是宏任务

代码执行顺序口诀:先同步后异步,先微任务后宏任务

总之,同微宏

到此,相信大家对“JavaScript异步怎么理解”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI