Node.js and Airtable: Async function not resolving promise as expected

I’m having trouble with an async function in my Node.js app that’s supposed to fetch data from Airtable. The problem is that the await keyword doesn’t seem to be working as it should. The function returns undefined before the actual data comes through.

Here’s a simplified version of what I’m dealing with:

async function fetchStuff(id) {
  return await myDatabase('Items')
    .select({
      filterByFormula: `{id} = '${id}'`
    })
    .firstPage((error, items) => {
      if (error) {
        console.error(error);
        return {};
      }
      console.log(items[0].fields);
      return items[0].fields;
    });
}

myArray.map(async (item) => {
  let info = getItemInfo(item);
  let result = await fetchStuff(info.id);
  console.log(result);
});

The console output shows undefined multiple times, followed by the actual data objects. It’s like the await isn’t waiting for the promise to resolve. Any ideas on what I’m doing wrong here? I’m pretty new to async/await and promises, so I might be missing something obvious.

I’ve struggled with similar Airtable async issues before. The key is to wrap the Airtable query in a Promise, as others have mentioned. But here’s an additional tip that helped me:

Consider using the ‘all’ method instead of ‘firstPage’ if you’re only expecting one result. It’s cleaner and avoids potential pagination issues:

async function fetchStuff(id) {
  const records = await myDatabase('Items').select({
    filterByFormula: `{id} = '${id}'`
  }).all();
  return records[0]?.fields || {};
}

This approach simplifies your code and makes it more readable. Plus, it automatically handles errors, so you don’t need explicit error handling within the function. Just remember to use try/catch when calling fetchStuff in your map function to handle any potential errors gracefully.

The issue in your code stems from misusing the Airtable API’s callback pattern with async/await. The firstPage method expects a callback, but you’re trying to return from it directly. Instead, you should wrap the Airtable query in a Promise. Here’s how you can modify your fetchStuff function:

async function fetchStuff(id) {
  return new Promise((resolve, reject) => {
    myDatabase('Items')
      .select({
        filterByFormula: `{id} = '${id}'`
      })
      .firstPage((error, items) => {
        if (error) {
          console.error(error);
          reject(error);
        }
        resolve(items[0]?.fields || {});
      });
  });
}

This approach properly wraps the Airtable query in a Promise, allowing await to work as expected. The function will now return the resolved value, and your map function should behave correctly. Remember to handle potential errors in your calling code as well.

hey claire, i ran into similar issues. the problem is mixing callback and promise styles. try wrapping ur airtable query in a Promise like this:

async function fetchStuff(id) {
return new Promise((resolve, reject) => {
myDatabase(‘Items’).select({…}).firstPage((error, items) => {
if (error) reject(error);
resolve(items[0]?.fields || {});
});
});
}

this should fix it for ya!