异同点
- 相同点:都用于处理JavaScript中的异步任务,解决异步操作导致的代码执行顺序问题。
- 不同点:
- 回调函数:通过将一个函数作为参数传递给另一个异步执行的函数,在异步操作完成时调用。它容易导致回调地狱,代码可读性和维护性差。例如:
fs.readFile('file.txt', 'utf8', function(err, data) {
if (err) {
console.error(err);
return;
}
console.log(data);
});
- **Promise**:是一个代表异步操作最终完成(或失败)及其结果的对象。它通过链式调用解决了回调地狱问题,代码更易读。例如:
const fs = require('fs').promises;
fs.readFile('file.txt', 'utf8')
.then(data => {
console.log(data);
})
.catch(err => {
console.error(err);
});
- **async/await**:是基于Promise的语法糖,以同步风格编写异步代码,看起来更简洁直观。例如:
const fs = require('fs').promises;
async function readFileAsync() {
try {
const data = await fs.readFile('file.txt', 'utf8');
console.log(data);
} catch (err) {
console.error(err);
}
}
readFileAsync();
适用场景
- 回调函数:
- 场景:在简单的、一次性的异步操作中,并且代码逻辑不复杂时可以使用。例如在一些简单的事件监听回调场景。
- 示例:
document.addEventListener('click', function() {
console.log('Clicked!');
});
- Promise:
- 场景:当需要处理多个异步操作,并且这些操作存在链式依赖关系时,Promise的链式调用能很好地组织代码。例如,在一个需要依次进行多个API调用的场景中。
- 示例:
function apiCall1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Result of apiCall1');
}, 1000);
});
}
function apiCall2(result1) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result1 +'and result of apiCall2');
}, 1000);
});
}
apiCall1()
.then(result1 => apiCall2(result1))
.then(finalResult => console.log(finalResult));
- async/await:
- 场景:当异步操作逻辑复杂,需要大量的异步操作组合,并且希望代码尽可能以同步的方式书写和阅读时,async/await是最佳选择。例如,在处理复杂的数据库事务时。
- 示例:
const mysql = require('mysql2/promise');
async function transaction() {
const connection = await mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'test'
});
try {
await connection.beginTransaction();
await connection.execute('UPDATE users SET balance = balance - 100 WHERE id = 1');
await connection.execute('UPDATE users SET balance = balance + 100 WHERE id = 2');
await connection.commit();
console.log('Transaction completed successfully');
} catch (err) {
await connection.rollback();
console.error('Transaction failed', err);
} finally {
connection.end();
}
}
transaction();