When AI Forgets How Async/Await Works
"Can you modernize this callback-based code?" Simple request. The AI responded with code that used callbacks, promises, async/await, and .then() chains. In the same function. It was like watching someone use a fork, spoon, knife, and their hands to eat soup.
Here's the archaeological dig through JavaScript history that AI created.
The Original Code (Callbacks)
function loadUserData(userId, callback) {
getUser(userId, (err, user) => {
if (err) return callback(err);
getOrders(user.id, (err, orders) => {
if (err) return callback(err);
getPayments(user.id, (err, payments) => {
if (err) return callback(err);
callback(null, { user, orders, payments });
});
});
});
}
Classic callback hell. The AI was asked to modernize it. What came back was... special.
The AI's "Modern" Version
async function loadUserData(userId, callback) {
try {
const user = await new Promise((resolve, reject) => {
getUser(userId, (err, data) => {
if (err) reject(err);
else resolve(data);
});
});
getOrders(user.id).then(orders => {
getPayments(user.id, async (err, payments) => {
if (err) {
return callback(err);
}
const result = await Promise.resolve({
user,
orders: await orders,
payments
});
callback(null, result);
}).catch(error => {
throw error; // This does nothing useful
});
});
} catch (err) {
callback(err);
}
}
Let's count the async patterns:
- ✓ async function declaration
- ✓ await
- ✓ new Promise()
- ✓ .then()
- ✓ Callback parameter
- ✓ Callback inside async function
- ✓ await Promise.resolve() (why?)
- ✓ .catch() that throws (defeating its purpose)
It's async/await having an identity crisis.
More Async Confusion From Production
The Unnecessary Await
// AI generated this
async function getRandomNumber() {
const number = await Math.random();
return await Promise.resolve(number);
}
// Math.random() isn't async...
The Promise Constructor Antipattern
// AI's "helpful" refactor
async function fetchData(url) {
return new Promise(async (resolve, reject) => {
try {
const response = await fetch(url);
const data = await response.json();
resolve(data);
} catch (error) {
reject(error);
}
});
}
// Just... return the promise from fetch!
The Callback-Promise Hybrid Monster
// I wish I was making this up
function saveUser(userData, callback) {
return new Promise((resolve) => {
database.save(userData).then(result => {
callback(null, result);
resolve(result);
}).catch(err => {
callback(err);
resolve(undefined); // ???
});
});
}
// Pick a pattern! ANY pattern!
The Await-Then Tango
// AI couldn't decide between await and .then()
async function processData(input) {
const step1 = await transform(input);
return await process(step1).then(async (step2) => {
const step3 = await validate(step2);
return step3;
}).then(result => {
return Promise.resolve(result);
});
}
// It's like using both belt and suspenders, then adding glue
The Race Condition Generator
// AI tried to parallelize, created race conditions instead
async function updateUserStats(userId) {
const user = await getUser(userId);
// These all modify the same user object
updateLoginCount(user); // Not awaited
updateLastSeen(user); // Not awaited
await updateActivityLog(user); // Only this is awaited
await saveUser(user); // Race condition: other updates might not be done
}
Why AI Gets Confused
1. Training on Historical Code
AI learned from 15 years of JavaScript evolution. It's seen callbacks (2009), promises (2012), and async/await (2017) all mixed together in tutorials.
2. No Understanding of Time
AI doesn't grasp that async/await replaced callbacks. To AI, they're all equally valid tools to use simultaneously.
3. Pattern Matching Gone Wrong
Sees async function? Add await! Sees callback? Keep it! Sees promise? Add .then()! Why not all three?
The Actually Modern Version
// What it should have been
async function loadUserData(userId) {
const user = await getUser(userId);
const [orders, payments] = await Promise.all([
getOrders(user.id),
getPayments(user.id)
]);
return { user, orders, payments };
}
// That's it. That's the whole function.
AI Async Antipatterns Hall of Fame
The Forgotten Await
async function deleteUser(userId) {
const user = getUser(userId); // Forgot await
console.log(user.name); // user is a Promise, not an object
}
The Synchronous Async
// AI marks it async but never uses await
async function calculateTotal(items) {
let total = 0;
for (const item of items) {
total += item.price * item.quantity;
}
return total;
}
The Try-Catch Confusion
async function riskyOperation() {
try {
doSomethingSync(); // This can throw
} catch (e) {
console.error(e);
}
// AI puts async operation outside try-catch
const result = await doSomethingAsync(); // Uncaught rejections!
return result;
}
Rules for AI Async Code
- Pick ONE pattern - Either callbacks OR promises OR async/await
- If async/await, no .then() - That's the whole point
- If it's not async, don't await it - Math.random() isn't a promise
- Wrap all awaits in try-catch - Or errors vanish into the void
- Use Promise.all() for parallel operations - Not sequential awaits
The Prompt That Works
"Convert this callback-based code to use ONLY async/await.
Rules:
- No callbacks in the final version
- No .then() or .catch()
- Use try-catch for error handling
- Use Promise.all() for parallel operations
- If a function doesn't return a promise, don't await it"
Testing AI's Async Understanding
// Give AI this test
"Make this code properly handle errors:"
async function fetchUserWithRetry(userId) {
const user = await fetchUser(userId);
return user;
}
// Good AI adds:
async function fetchUserWithRetry(userId, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await fetchUser(userId);
} catch (error) {
if (i === retries - 1) throw error;
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
}
}
}
// Bad AI adds .then() and callbacks mixed with await
AI mixing async patterns is like watching someone write with their left hand, right hand, and a foot simultaneously. Impressive flexibility, terrible results. The evolution from callbacks to promises to async/await was supposed to make code cleaner, not give us the option to use all three at once. When asking AI to modernize async code, be very specific about which century's JavaScript patterns you want to use.