一、Promise
*1. 概念:
- Promise 是 JavaScript 中处理异步操作的一种对象,它表示一个异步操作的最终完成(或失败)及其结果值。一个 Promise 对象处于以下三种状态之一:
- Pending(进行中):初始状态,既不是成功,也不是失败状态。
- Fulfilled(已成功):意味着操作成功完成。
- Rejected(已失败):意味着操作失败。
*2. 创建 Promise 对象:
let myPromise = new Promise((resolve, reject) => {// 异步操作setTimeout(() => {let success = true;if (success) {resolve('操作成功');} else {reject('操作失败');}}, 1000);
});
- 在上述代码中,
new Promise()
接收一个函数作为参数,该函数接收两个参数resolve
和reject
,分别用于将 Promise 对象的状态从Pending
转变为Fulfilled
或Rejected
。
*3. 使用 Promise 对象:
myPromise.then((result) => {console.log(result); // 操作成功时的处理}).catch((error) => {console.error(error); // 操作失败时的处理});
then()
方法用于添加成功状态的回调函数,当 Promise 的状态变为Fulfilled
时会调用该函数并传入结果。catch()
方法用于添加失败状态的回调函数,当 Promise 的状态变为Rejected
时会调用该函数并传入错误信息。
*4. 链式调用:
- Promise 可以进行链式调用,以便处理多个异步操作:
let firstPromise = new Promise((resolve, reject) => {setTimeout(() => {resolve('第一个操作完成');}, 1000);
});firstPromise.then((result) => {console.log(result);return new Promise((resolve, reject) => {setTimeout(() => {resolve('第二个操作完成');}, 1000);});}).then((result) => {console.log(result);}).catch((error) => {console.error(error);});
- 在这个例子中,第一个
then()
处理第一个 Promise 的结果,并返回一个新的 Promise,后续的then()
会处理新 Promise 的结果。
*5. Promise.all 和 Promise.race:
Promise.all
用于处理多个 Promise 实例,当所有的 Promise 都完成时,才会执行then()
方法:
let promise1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('Promise 1 完成');}, 1000);
});
let promise2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('Promise 2 完成');}, 2000);
});Promise.all([promise1, promise2]).then((results) => {console.log(results); // ['Promise 1 完成', 'Promise 2 完成']}).catch((error) => {console.error(error);});
Promise.race
用于处理多个 Promise 实例,只要其中一个 Promise 完成,就会执行then()
方法:
Promise.race([promise1, promise2]).then((result) => {console.log(result); // 'Promise 1 完成'}).catch((error) => {console.error(error);});
二、async 和 await
*1. async 函数:
async
关键字用于声明一个异步函数,该函数会隐式地返回一个 Promise 对象:
async function asyncFunction() {return '这是一个 async 函数的结果';
}
- 调用
asyncFunction()
会返回一个 Promise 对象,可使用then()
方法来处理结果:
asyncFunction().then((result) => {console.log(result);
});
*2. await 关键字:
await
关键字只能在async
函数中使用,它会暂停async
函数的执行,直到 Promise 被解决或被拒绝:
async function asyncFunction() {let promise = new Promise((resolve, reject) => {setTimeout(() => {resolve('Promise 已解决');}, 1000);});let result = await promise; // 暂停直到 promise 完成console.log(result);
}
asyncFunction();
- 在这个例子中,
await
等待promise
的解决,然后将结果存储在result
中并继续执行后续代码。
*3. 错误处理:
- 可以使用
try...catch
语句在async
函数中处理错误:
async function asyncFunction() {try {let promise = new Promise((resolve, reject) => {setTimeout(() => {reject('Promise 已失败');}, 1000);});let result = await promise;console.log(result);} catch (error) {console.error(error);}
}
asyncFunction();
*4. 结合使用 async 和 await 进行多个异步操作:
async function asyncFunction() {try {let result1 = await new Promise((resolve, reject) => {setTimeout(() => {resolve('第一个操作完成');}, 1000);});console.log(result1);let result2 = await new Promise((resolve, reject) => {setTimeout(() => {resolve('第二个操作完成');}, 1000);});console.log(result2);} catch (error) {console.error(error);}
}
asyncFunction();
- 在上述代码中,使用
await
可以让代码看起来更像同步代码,使异步操作的流程更易于理解和管理。
*5. 优势:
- 简洁性:使用
async
和await
可以使异步代码看起来更像同步代码,提高代码的可读性和可维护性,避免了大量的then()
和catch()
链式调用。 - 错误处理:使用
try...catch
语句可以更方便地处理异步操作中的错误,使错误处理更直观。
三、总结
- Promise:是处理异步操作的基础,提供了一种更优雅和灵活的方式来处理异步操作,避免了回调地狱(callback hell),通过状态管理和链式调用让异步代码更易于管理。
- async 和 await:是对 Promise 的进一步优化,使用
async
声明的函数会返回 Promise,await
可以暂停async
函数的执行等待 Promise 的结果,让异步代码看起来更像同步代码,大大提高了代码的可读性和可维护性,是现代 JavaScript 中处理异步操作的首选方式。
通过使用 Promise、async 和 await,可以更有效地管理 JavaScript 中的异步操作,提高代码的可读性和可维护性,使复杂的异步操作流程更易于理解和处理。
四、async 函数的调用逻辑
示例代码解析:
async function asyncFunction() {try {let result1 = await new Promise((resolve, reject) => {setTimeout(() => {resolve('第一个操作完成');}, 1000);});console.log(result1);let result2 = await new Promise((resolve, reject) => {setTimeout(() => {resolve('第二个操作完成');}, 1000);});console.log(result2);} catch (error) {console.error(error);}
}
asyncFunction();
当你调用一个 async
函数时,如 asyncFunction()
,该函数内部的代码逻辑会被执行,同时它会返回一个 Promise
对象。这与普通函数的调用有一些相似之处,但也有重要的区别。
-
相似之处:
- 像普通函数一样,调用
asyncFunction()
会触发函数内部代码的执行。 - 函数会按照其内部的逻辑顺序执行,包括变量声明、条件语句、循环等。
- 像普通函数一样,调用
-
区别:
async
函数内部可以使用await
关键字暂停函数的执行,等待Promise
对象的解析。- 函数的返回值会被自动包装在一个
Promise
对象中,即使你在函数内部没有显式地返回一个Promise
。
五、代码逻辑的执行顺序
在你提供的 asyncFunction()
代码中,以下是代码的执行顺序:
- 调用
asyncFunction()
,函数开始执行。 - 进入
try
块。 - 遇到
await new Promise((resolve, reject) => {...})
:- 这里会创建一个新的
Promise
对象,setTimeout
函数被调用,并且resolve('第一个操作完成')
将在 1000 毫秒后执行。 await
关键字会暂停asyncFunction()
的执行,等待这个Promise
的解析。
- 这里会创建一个新的
- 一旦第一个
Promise
被解析(即resolve('第一个操作完成')
被调用):asyncFunction()
会继续执行,result1
被赋值为'第一个操作完成'
。console.log(result1)
被调用,输出'第一个操作完成'
。
- 然后遇到第二个
await new Promise((resolve, reject) => {...})
:- 同样的过程,会等待另一个
Promise
的解析。
- 同样的过程,会等待另一个
- 当第二个
Promise
被解析:result2
被赋值为'第二个操作完成'
,console.log(result2)
输出'第二个操作完成'
。
六、函数的返回值
asyncFunction()
调用会返回一个 Promise
对象。你可以像使用其他 Promise
一样使用 then()
和 catch()
方法:
asyncFunction().then(() => {console.log('asyncFunction 已完成');}).catch((error) => {console.error('出现错误:', error);});
- 即使
asyncFunction()
内部没有显式地使用return
语句,它仍然会返回一个Promise
对象,该对象在函数内部代码全部执行完成后会被解析(如果没有错误发生)。
七、总结
- 调用
asyncFunction()
会执行函数内部的代码逻辑。 - 函数内部的
await
关键字会暂停函数的执行,直到Promise
对象被解析。 - 函数会隐式地返回一个
Promise
对象,你可以使用then()
和catch()
方法处理函数的完成或错误状态。
以下是一个更完整的示例,展示如何使用 asyncFunction()
的返回 Promise
:
async function asyncFunction() {try {let result1 = await new Promise((resolve, reject) => {setTimeout(() => {resolve('第一个操作完成');}, 1000);});console.log(result1);let result2 = await new Promise((resolve, reject) => {setTimeout(() => {resolve('第二个操作完成');}, 1000);});console.log(result2);return '函数完成';} catch (error) {console.error(error);return '函数出错';}
}asyncFunction().then((finalResult) => {console.log(finalResult); // 输出 "函数完成"}).catch((error) => {console.error(error);});
代码解释:
asyncFunction()
中的代码会按照正常顺序执行,但会在await
处暂停,等待Promise
解析。- 最终,
asyncFunction()
会返回一个Promise
,你可以使用then()
来处理最终的结果或使用catch()
来处理错误。
总之,async
函数的调用会执行内部代码,同时通过 await
可以方便地处理异步操作,并且返回的 Promise
对象允许你使用 then()
和 catch()
来处理最终结果和错误,为处理异步操作提供了一种简洁和直观的方式。
注意事项:
- 确保在
async
函数中使用await
时,只在Promise
前使用,否则会导致语法错误。 await
只能在async
函数中使用,不能在普通函数中使用。