一、async/await基础语法
在Node.Js编程中,async关键字用于定义异步函数,这个异步函数执行完会返回一个Promise对象,异步函数的内部可以使用await关键字来暂停当前代码的继续执行,直到Promise操作完成。
在用法上,async关键字主要用于声明一个异步函数,await关键字主要用于等待Promise操作的返回结果,若await等待的Promise操作被rejected,此时会抛出异常,需要对异常采用"try/catch"处理。
async/await的语法格式:
async function() {
await [Asynchronous Action]}
async/await代码样例:
1.等待Promise执行结果,并利用try/catch捕获异常
//定义异步函数
async function fetchData() {
try {
//异步操作,从API获取数据
//使用await等待函数执行完成
const response = await fetch('https://test.com/');
const data = await response.json();
console.log('The data is:', data);
} catch (error) {
console.error('Err occured:', error);
}
}
//调用异步函数
fetchData();
2.async时序测试
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2 finish');
}
console.log('script start');
async1();
console.log('script end');
运行结果:
script start
async1 start
async2 finish
script end
async1 end
二、async/await和Promise的关系
1.async/await的语法是基于Promise来实现的。
2.async/await对Promise进行了封装,异步编程时避免了繁琐的Promise链式调用。
3.async/await的设计是为了简化Promise异步编程的实现方式,代码可读性更强。
4.async/await基于Promise增加了对执行步骤的控制,可以通过await来暂停/恢复执行。
基于Promise实现的异步操作:
fetchData()
.then(data => process(data))
.then(result => save(result))
.catch(err => console.error(err));
基于async/await实现的异步操作:
try {
const data = await fetchData();
const result = await process(data);
await save(result);
} catch (err) {
console.error(err);
}
以上代码实现中,基于".then"实现的连续操作会让每一个步骤立即执行,基于await实现的连续操作可以让当前步骤暂停等待。
以下两段代码的实现效果相同:
Demo1:基于async实现的Hello打印
async function func() {
return "Hello";
}
func().then(
console.log("Print Hello")
);
运行结果:
Print Hello
Demo2:基于Promise实现的Hello打印
function func() {
return Promise.resolve("Hello");
}
func().then(
console.log("Print Hello")
);
运行结果:
Print Hello
三、利用Promise.all实现并发编程
Promise.all用于处理多个Promise任务的并发执行,Promise.all执行完会返回一个新的Promise对象。
基础语法:
Promise.all(iterable);
调用Promise.all的时候输入一个可迭代对象,比如数组,这个可迭代对象包含多个Promise实例,如果多个Promise实例全部执行成功,会返回按顺序排列的resolved数组,如果任意一个Promise实例执行失败会立即抛出第一个失败的Promise实例的reject原因,其他Promise实例仍会执行。
代码样例:
const p1 = Promise.resolve(1);
const p2 = new Promise(resolve => setTimeout(() => resolve(2), 1000));
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
.then(results => console.log(results));
运行结果:
[ 1, 2, 3 ]
Promise.all与await组合,在实现并发操作时的代码范式:
const [res1, res2] =
await Promise.all([task1(), task2()]);
Promise.all代码实战:模拟api并发请求
async function fetchData(endpoint, delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = 1;
success
? resolve(`${endpoint} response (${delay}ms delay)`)
: reject(`${endpoint} timeout`);
}, delay);
});
}
async function executeRequests() {
try {
const requests = [
fetchData('/users', 1200),
fetchData('/posts', 800),
fetchData('/comments', 1500)
];
console.log('Starting parallel requests...');
const results = await Promise.all(requests);
console.log('\nAll requests completed:');
results.forEach((res, index) =>
console.log(`Result ${index + 1}:`, res)
);
return results;
} catch (error) {
console.error('\nError:', error);
throw new Error(`Process failed: ${error}`);
}
}
(async () => {
try {
const data = await executeRequests();
console.log('\nFinal data:', JSON.stringify(data, null, 2));
} catch (err) {
console.error('Global error handler:', err.message);
}
})();
运行结果:
Starting parallel requests...
All requests completed:
Result 1: /users response (1200ms delay)
Result 2: /posts response (800ms delay)
Result 3: /comments response (1500ms delay)
Final data: [
"/users response (1200ms delay)",
"/posts response (800ms delay)",
"/comments response (1500ms delay)"
]
四、代码实战
Demo1:基于async/await和Dom实现的模拟网页登录验证
<!DOCTYPE html>
<html>
<head>
<title>Async/Await Web Demo</title>
<style>
.container { padding: 20px; max-width: 600px; margin: 0 auto; }
button { padding: 10px 20px; background: #2196F3; color: white; border: none; cursor: pointer; }
.loader { display: none; border: 3px solid #f3f3f3; border-top: 3px solid #3498db; border-radius: 50%; width: 20px; height: 20px; animation: spin 1s linear infinite; }
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
.result-section { margin-top: 20px; padding: 15px; background: #f5f5f5; }
</style>
</head>
<body>
<div class="container">
<h2>Async Operations Demo</h2>
<button onclick="executeOperations()">Run Async Tasks</button>
<div id="loading" class="loader"></div>
<div id="results" class="result-section"></div>
</div>
<script>
const asyncOperations = {
fetchUser: () => new Promise(resolve =>
setTimeout(() => resolve({ id: 1, name: 'John Doe' }), 1200)),
getStats: () => new Promise(resolve =>
setTimeout(() => resolve({ visits: 1520, active: true }), 800)),
validate: () => new Promise((resolve, reject) =>
setTimeout(() => Math.random() > 0.3
? resolve('Validation passed')
: reject('Error: Validation failed'), 1000))
};
async function executeOperations() {
const resultsDiv = document.getElementById('results');
const loader = document.getElementById('loading');
try {
// Clear previous results
resultsDiv.innerHTML = '';
loader.style.display = 'inline-block';
// Execute parallel async operations
const [user, stats, validation] = await Promise.all([
asyncOperations.fetchUser(),
asyncOperations.getStats(),
asyncOperations.validate()
]);
// Build result display
resultsDiv.innerHTML = `
<h3>Results:</h3>
<p>User: ${user.name}</p>
<p>Visits: ${stats.visits}</p>
<p>Status: ${validation}</p>
`;
} catch (error) {
resultsDiv.innerHTML = `<div style="color: red;">${error}</div>`;
} finally {
loader.style.display = 'none';
}
}
</script>
</body>
</html>
运行结果:


Demo2:基于async/await实现的音乐下载器
<!DOCTYPE html>
<html>
<head>
<title>音乐下载模拟器</title>
<style>
.progress-bar { width: 200px; height: 20px; border: 1px solid #ccc; }
.progress { height: 100%; background: #4CAF50; transition: width 0.3s; }
</style>
</head>
<body>
<button onclick="startDownloads()">开始下载全部歌曲</button>
<div id="downloadStatus"></div>
<script>
async function downloadSong(songName, duration) {
const statusDiv = document.getElementById('downloadStatus');
const item = document.createElement('div');
item.innerHTML = `${songName}: <div class="progress-bar"><div class="progress" style="width:0%"></div></div>`;
statusDiv.appendChild(item);
let progress = 0;
return new Promise((resolve, reject) => {
const interval = setInterval(() => {
progress += 20;
item.querySelector('.progress').style.width = `${progress}%`;
if (progress >= 100) {
clearInterval(interval);
resolve(`${songName} 下载完成`);
}
}, duration / 5); // 分5次完成进度更新
});
}
// 启动全部下载(并行执行)
async function startDownloads() {
try {
const songs = [
{ name: "音乐1.mp3", duration: 2000 },
{ name: "音乐2.mp3", duration: 2500 },
{ name: "音乐3.mp3", duration: 1800 }
];
const promises = songs.map(song =>
downloadSong(song.name, song.duration)
);
await Promise.all(promises);
alert("所有文件下载完成!");
} catch (error) {
console.error("下载失败:", error);
}
}
</script>
</body>
</html>
运行结果:

参考阅读:
https://www.programiz.com/javascript/async-await
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
https://www.geeksforgeeks.org/explain-async-await-with-promises-in-node-js/
923

被折叠的 条评论
为什么被折叠?



