告别"回调地狱"!Promise让异步代码"一线生机"

什么是异步

我们都知道代码执行时,v8把这段代码先编译再运行,此时cpu就会接受一个指令来执行上下文环境,这时候用的时间就叫做进程。执行指令的时间就是一个线程,所以一个进程可以有多个线程。但是我们的v8编译器跟别的编程语言就有点不一样来看下面的代码。

ini 复制代码
 let a=1
setTimeout(()=>{
    a=2
},1000)
console.log(a);

如果按照正常的编译顺序这时候输出打印的a就是2,但是我们可以看到这时的结果是1。很显然,v8是直接先执行了第一行与第五行的代码把中间这个定时器挂起了。

那这是为什么呢?

js默认是单线程运行的(v8默认只会开一个主线程来跑js代码)

  1. 因为js设计之处是浏览器的脚本语言,设计成单线程可以节约用户的设备性能
  2. js代码中存在耗时执行的,会被v8挂起,先执行不耗时的(同步代码)

这时候这种编程方式我们就叫作异步

如何解决异步

1.回调函数(初级)

来看这段代码,首先肯定就是先执行不消耗时间的指令所以先输出打印baz,a再是其他另外两个,但是我有没有一种方法可以foo先执行再是bar最后baz呢?

javascript 复制代码
let a=1
function foo(){
    setTimeout(()=>{
        a=2
        
        console.log('foo',a);
        
    
    },1000)
}
function bar(){
    setTimeout(()=>{
        a=3
        
        console.log('bar',a);
        
    
    },2000)
}
function baz(){
    console.log('baz',a);
}
foo()

这时候我们就可以用到回调函数,把baz放进bar里面,把bar放进foo里面,形成一个嵌套。

scss 复制代码
let a=1
function foo(){
    setTimeout(()=>{
        a=2
        bar()
        console.log('foo',a);
        
    
    },1000)
}
function bar(){
    setTimeout(()=>{
        a=3
        baz()
        console.log('bar',a);
        
    
    },2000)
}
function baz(){
    console.log('baz',a);
}
foo()

但是如果代码这样写的话,代码量大的话,就容易嵌套过深,形成回调地狱,我们维护代码时难以维护,一个函数有问题,一整个代码运行不了。所以这种方法虽然可行但是还是不够完美。

2.promise解决异步(高级)

我们用promise来以一个更加优雅的方式来解决这个问题,来看代码

javascript 复制代码
let a=1
function foo(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
        a=2
        console.log('foo',a);
        resolve()
    },2000)
    })
}
function bar(){
   return new Promise((resolve,reject)=>{
     setTimeout(()=>{
        a=3
        
        console.log('bar',a);
        resolve()
    },1000)
   })
}
function baz(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
        a=4
     console.log('baz',a);
     resolve() 
    },500)
    })
    
}
foo().then(()=>{
    return bar()
})
.then(()=>{
    return baz()
})

在三个函数加入promise Promise 有三种状态:

  1. pending(进行中) - 初始状态
  2. fulfilled(已成功) - 操作成功完成
  3. rejected(已失败) - 操作失败、

Promise 创建后会立即执行 这时候每个promise对象的状态会被修改为成功,而.then顾名思义就是下一个,执行完函数里的再执行.then。而then源码也默认返回了一个promise对象,状态继承了前面的foo。return 让 then 返回的promise状态根据bar返回的promise状态改变

3.Async/Await(进阶)

这里这样写虽然和promise差不多区别就在于最后把then换成了async,await.

  • 函数前面加一个async等同于函数内部返回一个promise实例对象

  • await 必须跟async 配合使用,并且await后面如果不接一个promise对象,await无法约束它

  • await fn() 把 fn() 当成同步看待

javascript 复制代码
let a=1
function foo(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
        a=2
        console.log('foo',a);
        resolve()
    },2000)
    })
}
function bar(){
   return new Promise((resolve,reject)=>{
     setTimeout(()=>{
        a=3
        
        console.log('bar',a);
        resolve()
    },1000)
   })
}
function baz(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
        a=4
     console.log('baz',a);
     resolve() 
    },500)
    })
    
}
async function fn(){
    await foo()
    await bar()
    baz()
}
fn()

总结:异步编程的"思想升华"

JavaScript的异步演进,就像人类处理多任务的智慧成长:

  1. 原始时代(回调) :一件事一件事做,记在脑子里(嵌套)
  2. 农业时代(Promise) :用记事本记下待办事项(任务队列)
  3. 信息时代(Async/Await) :用智能助手管理所有任务(自动化调度)

记住这三个核心点:

  1. JavaScript是单线程,但不代表它慢 ------ Event Loop让它高效处理并发
  2. Promise不是魔法,是一种状态管理机制 ------ 三种状态,两种结果
  3. Async/Await是语法糖,不是新东西 ------ 底层依然是Promise
相关推荐
威迪斯特1 分钟前
Flask:轻量级Web框架的技术本质与工程实践
前端·数据库·后端·python·flask·开发框架·核心架构
wuhen_n27 分钟前
JavaScript内置数据结构
开发语言·前端·javascript·数据结构
大鱼前端29 分钟前
为什么我说CSS-in-JS是前端“最佳”的糟粕设计?
前端
不爱吃糖的程序媛31 分钟前
Capacitor:跨平台Web原生应用开发利器,现已全面适配鸿蒙
前端·华为·harmonyos
AC赳赳老秦34 分钟前
2026国产算力新周期:DeepSeek实战适配英伟达H200,引领大模型训练效率跃升
大数据·前端·人工智能·算法·tidb·memcache·deepseek
CHU72903535 分钟前
淘宝扭蛋机抽盒小程序前端功能解析:解锁趣味抽盒新体验
前端·小程序
-凌凌漆-1 小时前
【npm】npm的-D选项介绍
前端·npm·node.js
鹿心肺语1 小时前
前端HTML转PDF的两种主流方案深度解析
前端·javascript
海石1 小时前
去到比北方更北的地方—2025年终总结
前端·ai编程·年终总结
一个懒人懒人2 小时前
Promise async/await与fetch的概念
前端·javascript·html