用一句简单的话来理解异步代码:在 v8 的眼里,像定时器这种 “耗时任务” 就是异步的。注意与cpu耗时进行区分。
异步执行的 JavaScript 代码
JavaScript 是一门单线程的语言,但通过异步执行,可以实现非阻塞的操作,提高程序的性能和用户体验。本文将深入讨论 JavaScript 中的异步编程,包括回调函数、Promise 和 async-await。
回调函数
回调函数是一种处理异步操作的方式,通过将函数作为参数传递给另一个函数,在异步操作完成时调用该函数。然而,过多的回调嵌套可能导致回调地狱,使代码难以维护和理解。
回调地狱
回调地狱指的是在多层嵌套的回调函数中编写代码,降低了代码的可读性和可维护性。这种情况经常出现在复杂的异步场景中,使代码难以管理。
Promise
为了解决回调地狱的问题,ES6 引入了 Promise 对象,它提供了一种更结构化和清晰的方式来处理异步操作。
-
Promise 实例对象及 .then() 方法
Promise 实例对象表示一个异步操作的最终完成或失败,可以通过
resolve或reject方法来改变其状态。.then()方法用于注册在 Promise 对象状态变化时的回调函数。 -
resolve 方法及参数传递
当 Promise 的状态由 pending 变为 fulfilled 时,
resolve方法被调用。通过resolve(参数),可以将参数传递给后续.then()方法中的回调函数。 -
reject 方法及错误处理
如果异步操作失败,可以调用
reject方法,将 Promise 对象的状态从 pending 变为 rejected。在链式调用中,可以通过.catch()方法捕获到reject的结果,并进行相应的错误处理。promiseObject .then((result) => { // 处理异步操作成功的情况 }) .catch((error) => { // 处理异步操作失败的情况 console.error('Error:', error); }); -
链式调用及返回值
.then()方法默认返回一个新的 Promise 对象,因此可以链式调用多个.then()。当.then()中有人为返回的 Promise 对象时,该返回值将作为唯一的返回值,影响链式调用。这意味着,后续的.then()方法将接在人为返回的 Promise 对象之后。
通过 resolve 和 reject,Promise 可以更好地处理异步操作成功和失败的情况,使得代码更加健壮和可控。
async-await
为了进一步简化异步代码的编写,ES2017 引入了 async 和 await 关键字。async 用于定义一个返回 Promise 对象的异步函数,而 await 用于等待 Promise 对象的解决。
使用 async-await 可以使异步代码看起来更像同步代码,增强了可读性。
function xq() {
return new Promise((resolve, reject) => {
setTimeout (() => {
console.log('涛涛相亲了');
resolve('相亲成功') //resolve 被调用 .then 才会生效
},2000)
})
}
function marry() {
return new Promise((resolve, reject) => {
setTimeout (() => {
console.log('涛涛结婚了');
resolve()
},1000)
})
}
function baby() {
console.log('小小涛');
}
xq()
.then((res) => {
console.log(res) //resove 传递的参数被.then接收到
return marry()// .then 默认返回一个Promise对象 所以第2个.then 认错了(需要接到marry后)。所以return marry
})
.then(() => {
baby()
})
大家需要处理异步任务时,也可以按以上模板进行编程。这样我们就实现了从相亲 => 结婚 => 生宝宝的过程。
在上述例子中,await 关键字等待异步操作完成,使得代码更加直观和易于理解。
通过掌握回调函数、Promise 和 async-await,你可以更好地处理 JavaScript 中的异步编程,提高代码的可维护性和可读性。