目录
一、回调地狱是什么?" >一、回调地狱是什么?
二、如何解决回调地狱" >二、如何解决回调地狱
1.Promise" >1.Promise
首页 web前端 前端问答 es6回调地狱是什么

es6回调地狱是什么

Feb 14, 2023 pm 02:58 PM
es6 回调地狱

在es6中,回调地狱就是多层回调函数相互嵌套,即回调函数中嵌套回调函数的情况;它是为了实现代码顺序执行而出现的一种操作,它会造成我们的代码可读性非常差,后期不好维护。es6中使用promise来解决回调地狱的问题。

es6回调地狱是什么

本教程操作环境:windows7系统、ECMAScript 6版、Dell G3电脑。

前言

在正式了解“回调地狱”之前,我们先了解两个概念:

1、回调函数

当一个函数作为参数传入另一个参数中,并且它不会立即执行,只有当满足一定条件后该函数才可以执行,这种函数就称为回调函数。我们熟悉的定时器和Ajax中就存在有回调函数:

setTimeout(function(){   //function(){console.log('执行了回调函数')}就是回调函数,它只有在3秒后才会执行
	console.log('执行了回调函数');
},3000)  //3000毫秒
登录后复制

这里的回调函数是function(){console.log('执行了回调函数')},在满足时间3秒后执行。

//1.创建异步对象
			var xhr=new XMLHttpRequest();
      //2.绑定监听事件(接收请求)
			xhr.onreadystatechange=function(){
				//此方法会被调用4次
				//最后一次,readyState==4
				//并且响应状态码为200时,才是我们要的响应结果 xhr.status==200
				if(xhr.readyState==4 && xhr.status==200){
					//把响应数据存储到变量result中
					var result=xhr.responseText;
					console.log(result);
				}
			}
      //3.打开链接(创建请求)
			xhr.open("get","/demo/ajaxDemo",true);
      //4.发送请求
			xhr.send();
登录后复制

这里的回调函数是xhr.onreadystatechange绑定的函数,在xhr.send()发送请求并拿到响应后执行。

2、异步任务

与之相对应的概念是“同步任务”,同步任务在主线程上排队执行,只有前一个任务执行完毕,才能执行下一个任务。异步任务不进入主线程,而是进入异步队列,前一个任务是否执行完毕不影响下一个任务的执行。同样,还拿定时器作为异步任务举例:

setTimeout(function(){
    console.log('执行了回调函数');
},3000)
console.log('111');
登录后复制

如果按照代码编写的顺序,应该先输出“执行了回调函数”,再输出“111”。但实际输出为:
在这里插入图片描述
这种不阻塞后面任务执行的任务就叫做异步任务。

接下来让我们看看什么是回调地狱。

一、回调地狱是什么?

根据前面我们可以得出一个结论:存在异步任务的代码,不能保证能按照顺序执行,那如果我们非要代码顺序执行呢?

比如我要说一句话,语序必须是下面这样的:武林要以和为贵,要讲武德,不要搞窝里斗。
我必须要这样操作,才能保证顺序正确:

        setTimeout(function () {  //第一层
            console.log('武林要以和为贵');
            setTimeout(function () {  //第二程
                console.log('要讲武德');
                setTimeout(function () {   //第三层
                    console.log('不要搞窝里斗');
                }, 1000)
            }, 2000)
        }, 3000)
登录后复制

在这里插入图片描述

可以看到,代码中的回调函数套回调函数,居然套了3层,这种回调函数中嵌套回调函数的情况就叫做回调地狱。

总结一下,回调地狱就是为是实现代码顺序执行而出现的一种操作,它会造成我们的代码可读性非常差,后期不好维护。

那该如何解决回调地狱呢?

二、如何解决回调地狱

1.Promise

Promise是js中的一个原生对象,是一种异步编程的解决方案,可以替换掉传统的回调函数解决方案。

  • Promise构造函数接收一个函数作为参数,我们需要处理的异步任务就卸载该函数体内,该函数的两个参数是resolve,reject。异步任务执行成功时调用resolve函数返回结果,反之调用reject。

  • Promise对象的then方法用来接收处理成功时响应的数据,catch方法用来接收处理失败时相应的数据。

  • Promise的链式编程可以保证代码的执行顺序,前提是每一次在than做完处理后,一定要return一个Promise对象,这样才能在下一次then时接收到数据。

下面是实例代码:

        function fn(str){
            var p=new Promise(function(resolve,reject){
                //处理异步任务
                var flag=true;
                setTimeout(function(){
                    if(flag){
                        resolve(str)
                    }
                    else{
                        reject('操作失败')
                    }
                })
            })
            return p;
        }

        fn('武林要以和为贵')
        .then((data)=>{
            console.log(data);
            return fn('要讲武德');
        })
        .then((data)=>{
            console.log(data);
            return fn('不要搞窝里斗')
        })
        .then((data)=>{
            console.log(data);
        })
        .catch((data)=>{
            console.log(data);
        })
登录后复制

在这里插入图片描述
但是Promise最大的问题就是代码冗余,原来的异步任务被Promise封装一下,不管什么操作都用than,就会导致一眼看过去全是then…then…then…,这样也是不利于代码维护的。

所以下面的async/await 可以时代码看起来更像同步代码。

2.async/await

首先我们看async关键字,他作为一个关键字放到声明函数前面,表示该函数为一个异步任务,不会阻塞后面函数的执行:

        async function fn(){
            return '不讲武德';
        }
        console.log(fn());
登录后复制

在这里插入图片描述
可以看到async函数返回数据时自动封装为一个Promise对象。

和Promise对象一样,处理异步任务时也可以按照成功和失败来返回不同的数据,处理成功时用then方法来接收,失败时用catch方法来接收数据:

        async function fn() {
            var flag = true;
            if (flag) {
                return '不讲武德';
            }
            else{
                throw '处理失败'
            }
        }
        fn()
        .then(data=>{
            console.log(data);
        })
        .catch(data=>{
            console.log(data);
        })

        console.log('先执行我,表明async声明的函数是异步的');
登录后复制

在这里插入图片描述
当把flag设置为false是,执行结果为:
在这里插入图片描述
async关键字说完了,我们看看awai关键字

  • await关键字只能在使用async定义的函数中使用
  • await后面可以直接跟一个 Promise实例对象(可以跟任何表达式,更多的是跟一个返回Promise对象的表达式)
  • await函数不能单独使用
  • await可以直接拿到Promise中resolve中的数据。
        //封装一个返回promise的异步任务
        function fn(str) {
            var p = new Promise(function (resolve, reject) {
                var flag = true;
                setTimeout(function () {
                    if (flag) {
                        resolve(str)
                    } else {
                        reject('处理失败')
                    }
                })
            })
            return p;
        }

        //封装一个执行上述异步任务的async函数
        async function test(){
            var res1=await fn('武林要以和为贵');  //await直接拿到fn()返回的promise的数据,并且赋值给res
            var res2=await fn('要讲武德');
            var res3=await fn('不要搞窝里斗');
            console.log(res1,res2,res3);
        }
        //执行函数
        test();
登录后复制

结果为:
在这里插入图片描述
为什么叫await等待呢,因为当代码执行到async函数中的await时,代码就在此处等待不继续往下执行,知道await拿到Promise对象中resolve的数据,才继续往下执行,这样就保证了代码的执行顺序,而且使异步代码看起来更像同步代码。

总结

总结一下,当我们写代码遇到异步回调时,我们想让异步代码按照我们想要的顺序执行,如果按照传统的嵌套方式,就会出现回调地狱,这样的代码不利于维护,我们可以通过Promise对象进行链式编程来解决,这样尽管可以解决问题,但是ES7给我们提供了更加舒适的async/await语法糖,可以使得异步代码看起来更像是同步代码。

【相关推荐:javascript视频教程web前端

以上是es6回调地狱是什么的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

ES6怎么求数组反转 ES6怎么求数组反转 Oct 26, 2022 pm 06:19 PM

在ES6中,可以利用数组对象的reverse()方法来实现数组反转,该方法用于颠倒数组中元素的顺序,将最后一个元素放在第一位,而第一个元素放在最后,语法“array.reverse()”。reverse()方法会修改原始数组,如果不想修改需要配合扩展运算符“...”使用,语法“[...array].reverse()”。

async是es6还是es7的 async是es6还是es7的 Jan 29, 2023 pm 05:36 PM

async是es7的。async和await是ES7中新增内容,是对于异步操作的解决方案;async/await可以说是co模块和生成器函数的语法糖,用更加清晰的语义解决js异步代码。async顾名思义是“异步”的意思,async用于声明一个函数是异步的;async和await有一个严格规定,两者都离不开对方,且await只能写在async函数中。

es6怎么找出2个数组中不同项 es6怎么找出2个数组中不同项 Nov 01, 2022 pm 06:07 PM

步骤:1、将两个数组分别转为set类型,语法“newA=new Set(a);newB=new Set(b);”;2、利用has()和filter()求差集,语法“new Set([...newA].filter(x =>!newB.has(x)))”,差集元素会被包含在一个set集合中返回;3、利用Array.from将集合转为数组类型,语法“Array.from(集合)”。

小程序为什么要将es6转es5 小程序为什么要将es6转es5 Nov 21, 2022 pm 06:15 PM

为了浏览器兼容。ES6作为JS的新规范,加入了很多新的语法和API,但现代浏览器对ES6新特性支持度不高,所以需将ES6代码转为ES5代码。在微信web开发者工具中,会默认使用babel将开发者ES6语法代码转换为三端都能很好支持的ES5的代码,帮助开发者解决环境不同所带来的开发问题;只需要在项目中配置勾选好“ES6转ES5”选项即可。

es5和es6怎么实现数组去重 es5和es6怎么实现数组去重 Jan 16, 2023 pm 05:09 PM

es5中可以利用for语句和indexOf()函数来实现数组去重,语法“for(i=0;i

es6暂时性死区是什么意思 es6暂时性死区是什么意思 Jan 03, 2023 pm 03:56 PM

在es6中,暂时性死区是一个语法错误,是指let和const命令使区块形成封闭的作用域。在代码块内,使用let/const命令声明变量之前,该变量都是不可用的,在变量声明之前属于该变量的“死区”;这在语法上,称为“暂时性死区”。ES6规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。

require是es6语法吗 require是es6语法吗 Oct 21, 2022 pm 04:09 PM

不是,require是CommonJS规范的模块化语法;而es6规范的模块化语法是import。require是运行时加载,import是编译时加载;require可以写在代码的任意位置,import只能写在文件的最顶端且不可在条件语句或函数作用域中使用;require运行时才引入模块的属性所以性能相对较低,import编译时引入模块的属性所所以性能稍高。

es6 map有序吗 es6 map有序吗 Nov 03, 2022 pm 07:05 PM

map是有序的。ES6中的map类型是一种储存着许多键值对的有序列表,其中的键名和对应的值支持所有数据类型;键名的等价性判断是通过调用“Objext.is()”方法来实现的,所以数字5与字符串“5”会被判定为两种类型,可以分别作为两种独立的键出现在程序中。

See all articles