什么是回调地狱?如何解决回调地狱问题_地狱回调
问题 如何 解决 什么 回调 地狱
2023-06-13 09:15:10 时间
一、什么是回调地狱呢?
地狱这个词不陌生吧!对,没错就是那个十八层地狱的地狱,一层一层的地狱。
1、同步API,异步API的区别
这个问题呢,需要从Node.js的API说起,这里就会有人问了?博主你不是说回调地狱的问题吗,怎么说到API了,别急,看博主一步一步的解释给你听:
同步API 是从上到下依次执行,前面的代码会阻塞后面的代码执行
请看下面这个代码
这里我写了一个for询还1000次,在循环里面打印,在循环体后面是另外的一个打印结果
结果是什么呢?
这个需要你自己去敲一下代码才能更好的了解喔!
for(var i=0; i<1000; i++){
console.log(i);
}
console.log('循环体后面的代码')
异步API不会等待API执行完后在向下执行代码
看下下面这个代码,会是如何执行呢?
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 在执行5
2、Node.js中的异步API
使用fs.readFile(‘./demo.txt’,(err,result) =>{});
上面这个就是一个异步API
是使用系统模块fs去查看文件
如果异步API后面的代码执行依赖当前异步API的执行结果,但实际上后续代码在执行的时候异步API还没有返回结果,这个问题怎么解决呢?
fs.readFile(‘./demo.txt’,(err,result) =>{});
console.log('文件打印结果')
3、写一个使用异步API,造成的回调地狱案例
案例需求:依次读取A文件,B文件,C文件
- 首先需要创建一个js的文件
- 然后分别创建1.txt 2.txt 3.txt
- 在每个文本里面写分别写上1 2 3
- 这样我们3个文件就创建好了,进入码代码的环节啦
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个呢
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);
})
})
})
})
})
})
})
})
})
})
});
这样你能理解了吗?这样一层回调嵌套一层回调,是不是有点像地狱的样子!这样的代码也不易去维护。
二、怎么解决回调地狱呢?
Promise的出现就是解决Node.js异步编程中回调地狱的问题
基础语法
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文件
- 文件可以就用之前的文件
- 开始代码的编写
//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、改进的方法
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 优化(异步函数)
异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了
const fn = async() =>{
};
async function fn(){
}
之前的案例,优化后的代码如下
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、总结
//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
相关文章
- ajax跨域解决方案_java如何解决跨域问题
- 如何安装win10和linux双系统。以及引导系统问题。
- redis缓存雪崩 缓存穿透 缓存击穿如何解决_缓存击穿问题
- API慢请求问题排查记录「1」
- MongoDB中null性能问题以及如何应对
- Java并发编程(实战):如何解决可见性和有序性问题
- MySQL编码异常:如何解决乱码问题(mysqlas乱码)
- 如何解决 Windows-Linux 双启动设置中显示时间错误的问题
- 如何处理Linux行尾的问题?(linux行尾)
- 如何解决Oracle数据库中的EXP报错问题?(exp报错oracle)
- 如何解决linux无法修改文件的问题?(linux不能修改文件)
- 如何解决MySQL创建数据库报错问题?(mysql创建数据库报错)
- 解决Oracle数据库文件(DBF)过大问题:如何压缩和分割文件。(oracledbf太大)
- MySQL中1215错误如何解决表格外键约束的问题(mysql中1215)
- 如何解决Cmd下MySQL无法打开的问题(cmd下打不开mysql)
- MySQL链接异常问题,如何诊断及解决(mysql一链接就停止)
- MySQL启动问题,如何解决一启动就停的情况(mysql一启动就停)
- MySQL Yog如何解决乱码问题(mysql yog 乱码)
- 中运行如何处理解决MySQL不在一个实例中运行问题的方法(MySQL不在一个实例)
- 解决单机Redis分区问题(单机redis如何分区)
- 如何有效避免Redis并发问题(如何防止redis的并发)
- 如何解决MySQL重装失败问题(mysql不能重装)
- 如何解决MySQL连接池获取失败问题(mysql不能获取连接池)
- 如何解决MySQL无法显示正在运行的问题(mysql不显示正在运行)
- 如何解决Redis的长连接问题(redis长连接问题)
- 如何解决Redis无法连接主机问题(redis连接不到主机)
- 如何解决无法安装Oracle10g的问题(oracle10g装不上)
- 如何解决Oracle 00927错误提示问题(oracle 00927)
- MSSQL2008不能用IP登录问题如何解决