Chaining API calls in Zapier with promises

Hey everyone, I’m having trouble with a Zapier trigger that’s intended to fetch API data in blocks of 500 items at a time. Each data group comes with a timestamp, and I need to use that timestamp to make the next API call. The code I experimented with tries to call a new function after each data block is received:

function fetchDataChunk(z, bundle, lastTimestamp) {
  return z.request({
    url: 'https://api.example.com/fetchData',
    params: { start: lastTimestamp }
  }).then(response => {
    if (response.status !== 200) {
      throw new Error('API error: ' + response.status);
    }
    return response.json;
  });
}

function collectAllData(z, bundle) {
  let collectedData = [];
  let lastTimestamp = 0;

  function loadNext() {
    return fetchDataChunk(z, bundle, lastTimestamp).then(dataBlock => {
      collectedData = collectedData.concat(dataBlock);
      if (dataBlock.length === 500) {
        lastTimestamp = dataBlock[dataBlock.length - 1].timestamp;
        return loadNext();
      }
      return collectedData;
    });
  }

  return loadNext();
}

module.exports = {
  perform: collectAllData
};

I keep getting an error from Zapier that says ‘Results must be an array, got: undefined’. The function that fetches the data block works correctly on its own. I am pretty new to working with promises, so any help or suggestions would be much appreciated!

I’ve encountered similar issues when working with chained API calls in Zapier. The problem likely stems from how Zapier handles asynchronous operations. Instead of using nested functions, try restructuring your code to use async/await syntax. This approach often works better with Zapier’s execution environment.

Here’s a modified version that might resolve your issue:

async function collectAllData(z, bundle) {
  let collectedData = [];
  let lastTimestamp = 0;

  while (true) {
    const response = await z.request({
      url: 'https://api.example.com/fetchData',
      params: { start: lastTimestamp }
    });

    if (response.status !== 200) {
      throw new Error('API error: ' + response.status);
    }

    const dataBlock = response.json;
    collectedData = collectedData.concat(dataBlock);

    if (dataBlock.length < 500) break;

    lastTimestamp = dataBlock[dataBlock.length - 1].timestamp;
  }

  return collectedData;
}

module.exports = {
  perform: collectAllData
};

This structure should be more compatible with Zapier’s expectations and hopefully resolve the ‘undefined’ error you’re experiencing.

As someone who’s worked extensively with Zapier and API integrations, I can relate to your struggle. The issue you’re facing is likely due to how Zapier handles promise chains. Here’s a trick I’ve found useful:

Instead of nesting functions, try flattening your promise chain and use Array.reduce(). This approach has worked wonders for me in similar scenarios:

async function collectAllData(z, bundle) {
  let lastTimestamp = 0;
  let allData = [];

  while (true) {
    const response = await z.request({
      url: 'https://api.example.com/fetchData',
      params: { start: lastTimestamp }
    });

    if (response.status !== 200) {
      throw new Error(`API error: ${response.status}`);
    }

    const dataBlock = response.json;
    allData = allData.concat(dataBlock);

    if (dataBlock.length < 500) break;

    lastTimestamp = dataBlock[dataBlock.length - 1].timestamp;
  }

  return allData;
}

module.exports = { perform: collectAllData };

This structure maintains a single promise chain, which Zapier handles more reliably. It’s also more readable and easier to debug. Give it a shot and let me know if it resolves your issue!

hey isaac, i’ve dealt with similar zapier headaches before. have you tried using async/await instead of promise chains? it might solve your problem. here’s a quick example:

async function collectAllData(z, bundle) {
  let data = [];
  let timestamp = 0;
  while (true) {
    let chunk = await fetchDataChunk(z, bundle, timestamp);
    data = [...data, ...chunk];
    if (chunk.length < 500) break;
    timestamp = chunk[chunk.length - 1].timestamp;
  }
  return data;
}

this approach is usually easier for zapier to handle. lmk if it helps!