什么是回调地狱?如何解决回调地狱问题

什么是回调地狱?如何解决回调地狱问题

大家好,又见面了,我是你们的朋友全栈君。

一、什么是回调地狱呢? 地狱这个词不陌生吧!对,没错就是那个十八层地狱的地狱,一层一层的地狱。

1、同步API,异步API的区别这个问题呢,需要从Node.js的API说起,这里就会有人问了?博主你不是说回调地狱的问题吗,怎么说到API了,别急,看博主一步一步的解释给你听:

同步API 是从上到下依次执行,前面的代码会阻塞后面的代码执行

请看下面这个代码

代码语言:javascript代码运行次数:0运行复制这里我写了一个for询还1000次,在循环里面打印,在循环体后面是另外的一个打印结果

结果是什么呢?

这个需要你自己去敲一下代码才能更好的了解喔!

for(var i=0; i<1000; i++){

console.log(i);

}

console.log('循环体后面的代码')异步API不会等待API执行完后在向下执行代码

看下下面这个代码,会是如何执行呢?

代码语言:javascript代码运行次数:0运行复制console.log('代码开始执行')

//异步操作 setTimout

setTimout(() =>{

console.log('5秒后执行代码') },5000);//5000就是5秒

setTimout(() =>{

console.log('0秒后执行代码')},0);

console.loh('代码结束执行');

这里的执行顺序是:

代码开始执行

代码结束执行

0秒后执行代码

5秒后执行代码

逻辑梳理:先执行同步的API,在去执行异步的API

同步API有两个 分别是两个console.log

异步API也有两个 分别是setTimout

异步API里面的定时器会先执行0 在执行52、Node.js中的异步API代码语言:javascript代码运行次数:0运行复制 使用fs.readFile(‘./demo.txt’,(err,result) =>{});

上面这个就是一个异步API

是使用系统模块fs去查看文件如果异步API后面的代码执行依赖当前异步API的执行结果,但实际上后续代码在执行的时候异步API还没有返回结果,这个问题怎么解决呢?

代码语言:javascript代码运行次数:0运行复制 fs.readFile(‘./demo.txt’,(err,result) =>{});

console.log('文件打印结果')3、写一个使用异步API,造成的回调地狱案例案例需求:依次读取A文件,B文件,C文件

首先需要创建一个js的文件然后分别创建1.txt 2.txt 3.txt在每个文本里面写分别写上1 2 3这样我们3个文件就创建好了,进入码代码的环节啦代码语言:javascript代码运行次数:0运行复制const fs = require('fs')

fs.readFile('./1.txt','utf8',(err,result1) =>{

console.log(result1);

fs.readFile('./2.txt','utf8',(err,result2) =>{

console.log(result2);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

})

})

});执行这个js文件,执行结果是正确的,是不是没毛病!

但是这我们只写了3个,要是我们写18个呢

代码语言:javascript代码运行次数:0运行复制const fs = require('fs')

fs.readFile('./1.txt','utf8',(err,result1) =>{

console.log(result1);

fs.readFile('./2.txt','utf8',(err,result2) =>{

console.log(result2);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

fs.readFile('./3.txt','utf8',(err,result3) =>{

console.log(result3);

})

})

})

})

})

})

})

})

})

})

});这样你能理解了吗?这样一层回调嵌套一层回调,是不是有点像地狱的样子!这样的代码也不易去维护。

二、怎么解决回调地狱呢?代码语言:javascript代码运行次数:0运行复制 Promise的出现就是解决Node.js异步编程中回调地狱的问题代码语言:javascript代码运行次数:0运行复制基础语法

let promise = new Promise((resolve,reject) =>{

setTimout(() =>{

if(true){

//resolve将异步API的执行结果传递出去

resolve({

name:"张三"})

}else{

//reject 也是一个函数,当判断失败的时候,将结果传递出去

reject('失败了')

}

},2000);

})

//成功了

promise.then(result => console.log(result));//{name:‘张三’}

.catch(error => console.log(error));//失败了1、使用Promise来完成我们之前做的案例创建一个js文件文件可以就用之前的文件开始代码的编写代码语言:javascript代码运行次数:0运行复制//1、引入系统模块fS

const fs = require('fs');

//2、创建一个promise对象

let promise = new Promise((resolve,reject) =>{

fs.readFile('./1.txt','utf8',(err,result) =>{

if(err !=null){

reject(err);

}else{

resolve(result);

}

});

});

//文件成功的信息

promise.then((result) =>{

console.log(result);

})

//文件失败的信息

.catch((err) =>{

console.log(err);

})2、改进的方法代码语言:javascript代码运行次数:0运行复制const fs = require('fs')

function p1(){

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

fs.readFile('./1.txt','utf8',(err,result) =>{

resolve(result);

})

})

}

function p2(){

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

fs.readFile('./2.txt','utf8',(err,result) =>{

resolve(result);

})

})

}

function p3(){

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

fs.readFile('./3.txt','utf8',(err,result) =>{

resolve(result);

})

})

}

//依次执行1、2、3

p1().then((r1) =>{

console.log(r1);

//return p2

return p2();

})

.then((r2) =>{

console.log(r2);

//return p3()

return p3();

})

.then((r3) =>{

console.log(r3);

})读到这里,你知道什么是回调地狱了吗?并且如何解决它了吗?

切记!看代码或者看文章的记忆并不深刻哟,要自己去敲代码,这个在面试中也是经常会出现哟!码字不易,希望能一键三连

2021.3月31日更新

3、ES7 优化(异步函数)异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了

代码语言:javascript代码运行次数:0运行复制const fn = async() =>{

};代码语言:javascript代码运行次数:0运行复制async function fn(){

}之前的案例,优化后的代码如下

代码语言:javascript代码运行次数:0运行复制const fs = require('fs');

const promisify = require("util").promisify;

const readFile = promisify(fs.readFile);

async function run() {

let r1 = await readFile('./1.txt','utf8')

let r2 = await readFile('./2.txt','utf8')

let r3 = await readFile('./3.txt','utf8')

console.log(r1);

console.log(r2);

console.log(r3);

}

run();4、总结代码语言:javascript代码运行次数:0运行复制//1.在普通函数定义的前面加上async关键字 普通函数就变成的异步函数

//2.异步函数默认的返回值是promise对象

//3.在异步函数内部使用throw关键字进行错误的抛出

//await关键字

//1.它只能出现在异步函数中

//2.await promise 它可以暂停异步函数的执行 等待promise对象返回结果后在向下执行

async function p1() {

return '1';

}

async function p2() {

return '2';

}

async function p3() {

return '3';

}

async function run() {

let r1 = await p1()

let r2 = await p2()

let r3 = await p3()

console.log(r1);

console.log(r2);

console.log(r3);

}

run();版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/234800.html原文链接:https://javaforall.cn

相关推荐

苹果mp3报价(苹果MP3报价大全,最新价格一览!)
英国365老板

苹果mp3报价(苹果MP3报价大全,最新价格一览!)

📅 08-23 👁️ 9025
儿童眼神不对视,这4种情况家长要注意了!
英国365老板

儿童眼神不对视,这4种情况家长要注意了!

📅 07-03 👁️ 772
银行卡可用余额不足什么意思?账户状态与资金冻结原因