异步
console.log(1);
setTimeout(() => {
a = 2
console.log(2)
}, 1000)
console.log(3)
当程序中,遇到需要耗时的代码时,会将其挂起,等待后序代码运行结束后,再开始执行
js异步产生的原因
- js是一个单线程语言,一次只能干一件事(多线程执行执行开销性能高,开发难度大)
- js遇到需要耗时执行的代码就将其先挂起,等到后序不耗时的的代码执行完后来执行
解决异步
回调
回调函数是最早出现的异步编程方式。它的基本思想是将一个函数作为参数传递给另一个函数,这个被传递的函数会在某个异步操作完成时调用。
function fetchData(callback) {
setTimeout(() => {
const data = "some data";
callback(data);
}, 1000);
}
fetchData((data) => {
console.log(data); // 输出 "some data"
});
回调的缺陷: 回调地狱(Callback Hell)是指当你有多个异步操作需要依次执行,并且每个操作都依赖于前一个操作的结果时,代码会嵌套成多层回调函数,导致结构复杂、难以理解和维护。
function a(cb, cb2, cb3) {
setTimeout(() => {
console.log('a 执行完毕')
cb(cb2, cb3)
}, 1000)
}
function b(cb, cb3) {
setTimeout(() => {
console.log('b 执行完毕')
cb(cb3)
}, 1500)
}
function c(cb) {
setTimeout(() => {
console.log('c 执行完毕')
cb()
}, 500)
}
function d() {
console.log('d 执行完毕');
}
a(b, c, d)
代码被层层调用,报错难以找到问题
promise
Promise 是为了解决回调地狱(Callback Hell)问题而引入的。Promise 对象代表一个最终可能完成(并返回结果)或失败(并返回原因)的异步操作。
基本用法
创建一个 Promise
你可以使用 new Promise 构造函数来创建一个 Promise 对象。这个构造函数接受一个执行器函数(executor function),这个函数有两个参数:resolve 和 reject,它们都是函数。
let promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
let success = true; // 假设这是某种异步操作的结果
if (success) {
resolve('操作成功');
} else {
reject('操作失败');
}
}, 1000);
});
使用 Promise
Promise 对象有两个主要的方法:then 和 catch,用于处理成功和失败的情况。
promise
.then(result => {
console.log(result); // 输出: 操作成功
})
.catch(error => {
console.error(error); // 如果失败,则输出: 操作失败
});
Promise 的状态
一个 Promise 对象有以下三种状态:
- Pending(等待中) :初始状态,既不是成功也不是失败。
- Fulfilled(已成功) :意味着操作成功完成。
- Rejected(已失败) :意味着操作失败。
链式调用
then 方法返回一个新的 Promise,这使得可以进行链式调用。每个 then 方法可以接收两个函数作为参数,第一个函数是处理成功的情况,第二个函数(可选)是处理失败的情况。
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log(`最终结果: ${finalResult}`);
})
.catch(failureCallback);