Async calls (e.g., fetch()) return Promises, not immediate values. Direct return yields undefined. Focus: JavaScript (adapt for other langs).
Problem Example
function fetchData() {
let result;
fetch('https://api.example.com/data')
.then(data => { result = data; });
return result; // undefined
}
Solutions
1. Return Promise (Chain .then())
function fetchData() {
return fetch('https://api.example.com/data')
.then(response => response.json())
.catch(error => { throw error; });
}
// Usage
fetchData().then(data => console.log(data));
- Pros: Non-blocking. Cons: Nesting issues.
2. Async/Await (Recommended)
async function fetchData() {
const response = await fetch('https://api.example.com/data');
return await response.json();
}
// Usage
const data = await fetchData();
console.log(data);
- Pros: Readable, try/catch errors. Cons: Requires async callers.
3. Callbacks (Legacy)
function fetchData(callback) {
fetch('https://api.example.com/data')
.then(data => callback(null, data))
.catch(err => callback(err, null));
}
// Usage
fetchData((err, data) => { if (!err) console.log(data); });
- Pros: Simple. Cons: Control inversion.
Best Practices
-
Errors: Always
.catch()or try/catch. -
Parallel:
Promise.all([async1(), async2()]). -
Timeouts: Use
AbortController. -
Testing: Mock
fetchin Jest. -
Node:
node-fetchfor < v18.
Real Example: User Posts API
const fetch = require('node-fetch');
async function getPosts(userId) {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`);
return await res.json();
}
const posts = await getPosts(1); // Returns array
Key Takeaway
Use async/await for clean returns. Reduces bugs in 90% of cases.