You’re mixing async/await with callbacks, and eachPage isn’t returning the records you expect.
I’ve hit this exact problem building internal tools that pull from multiple Airtable bases. Your jobs.find() is async but you’re not waiting for it to finish.
Here’s my fix:
router.get('/', async function(req, res, next) {
const title = 'test';
try {
// Get all mentor records first
const mentorRecords = await mentors
.select({maxRecords: 6, view: "Grid view"})
.all();
// Add job data to each mentor
const enrichedRecords = await Promise.all(
mentorRecords.map(async (record) => {
try {
const jobRecord = await new Promise((resolve, reject) => {
jobs.find(record.fields["Quel est votre métier actuel"], (err, jobRecord) => {
if (err) reject(err);
else resolve(jobRecord);
});
});
return {
...record,
fields: {
...record.fields,
job: jobRecord.fields.Job
}
};
} catch (err) {
console.error('Error fetching job for mentor:', err);
return record; // Return mentor without job data if lookup fails
}
})
);
res.render('index', {title, records: enrichedRecords});
} catch (error) {
console.error('Error:', error);
res.status(500).send('Server error');
}
});
Key changes:
Use .all() instead of .eachPage() to get actual records
Wrap jobs.find in a Promise since it’s callback-based
Use Promise.all() to wait for all job lookups
Handle errors properly
This works great in production when you need to merge data from multiple sources.
The problem is eachPage doesn’t return a promise with your records - it just handles pagination. Hit this same issue with Airtable’s API last year.
Your async operations in the forEach loop aren’t being awaited, so the function finishes before job lookups complete. That’s why you’re getting a pending promise.
Ditch eachPage and use firstPage() or all() to actually get records back. Then handle the async job lookups properly. Since jobs.find() is callback-based, you’ll need to promisify it or use a library that converts callbacks to promises.
What worked for me: collect all mentor records first, then use Promise.allSettled() for job lookups in parallel. This way you won’t lose mentors if some job lookups fail - happens more than you’d think with external APIs.