Managing nested callbacks in Node.js when working with Airtable API

I’m pretty new to Node.js and trying to get better at it. I have an Airtable database and I need to fetch all records from a specific table. The Airtable Node.js API works fine for getting the data, but I want to store all these records in an array so I can export them later as JSON or Excel files.

Since the API calls are asynchronous, I’m using callbacks but I think I might be doing it wrong. I keep hearing about Promises as a better solution but I’m still learning how they work.

Here’s what I have so far:

var AirtableLib = require('airtable');
AirtableLib.configure({
    endpointUrl: 'https://api.airtable.com',
    apiKey: 'your-api-key-here'
});
var database = AirtableLib.base('your-base-id');
var viewName = "Grid view";

var dataArray = [];
database('Products').select({
    view: viewName
}).eachPage(function handlePage(recordList, getNext) {
    recordList.forEach(function(item) {
        dataArray.push({
            "Title": item.get('Title'),
            "Description": item.get('Description')
        });
    });
    getNext();
    processArray(dataArray);
}, function finished(err) {
    if (err) {
        console.log(err);
        console.log(dataArray);
    }
});

function processArray(dataArray) {
    convertToJson(dataArray);
    return dataArray;
}

function convertToJson(dataArray) {
    console.log(dataArray);
    return JSON.stringify(dataArray);
}

Should I switch to using Promises here? I’m worried about creating too many callback functions and making the code messy. Any advice on the best approach?

Your code has a bigger problem than callbacks vs Promises. You’re calling processArray(dataArray) inside handlePage, which runs after every page instead of waiting for all pages to finish. This’ll mess up your data. Move that processing logic to the finished callback - that’s where you get your complete dataset. Right now you’re processing incomplete data every time a new page loads. Your callback approach works fine here. The Airtable API’s eachPage method already handles all the pagination stuff for you. If you want cleaner code, sure, wrap it in a Promise, but you don’t need to. Callbacks are totally valid for this, especially when you’re learning. Get the data flow working right first, then worry about Promise complexity later.