Triggering multiple webhook calls in a "Code by Zapier" action

Viewed 129

I'm currently trying to create a for loop inside the "Code by Zapier" action. The intention of the code is to have a for-loop that executes 5 times; each time the loop triggers I want to hit a webhook.

Once the for loop is finished executing, I put a line of code using the callback function in order to exit the action successfully (not ending with a callback function triggers the error "You must return a single object or array of objects").

However, if I finish the action with the callback, then the webhook never gets hit/triggered (as if the fetch function is never executed or doesn't get to finish). If I don't use callback at the end (and use something like "return output = {data: data};", I get a "ReferenceError: output is not defined" error but the fetch request is executed and the webhook gets hit 5 times.

The code I use looks as follows:

var url = "https://hooks.zapier.com/hooks/catch/5506184/byko7zw/";
var i;
for (i = 0; i < 5; i++) {
  var headers = {
    "Content-type": "application/json",
  };

  var body = JSON.stringify({ data: "Hello, World!", number: i });

  fetch(url, { method: "POST", headers: headers, body: body }).then((res) => {
      console.log(res);
    })
    .catch(callback);
}

callback(null, {});

Would there be a way to successfully hit the webhook the designated number of times in the for loop and exit successfully instead of just one or the other? Any help or advice would be greatly appreciated!

2 Answers

Yes, it is possible! It will be easier to structure your code using await for the requests (rather than the older callback style while, while still valid, is pretty confusing).

Try something like this:

const url = "https://hooks.zapier.com/hooks/catch/5506184/byko7zw/";

for (let number = 0; number < 5; number++) {
  var headers = {
    "Content-type": "application/json",
  };

  const body = JSON.stringify({ data: "Hello, World!", number });

  const response = await fetch(url, {
    method: "POST",
    headers,
    body,
  });
  response.throwForStatus(); // exit if there are errors
  // you can log the response here, but you don't need to
}

// code steps have to return _something_
return { done: true };

This will work in a more predictable manner. One thing you may run into is that making 5 requests one after the other can be slow. If the exact order doesn't matter, you could parallelize them like so:

const url = "https://hooks.zapier.com/hooks/catch/5506184/byko7zw/";

var headers = {
  "Content-type": "application/json",
};

const numbers = [...Array(5).keys()]; // fancy way to get [0,1,2,3,4]
const promiseArray = numbers.map((number) =>
  fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify({ data: "Hello, World!", number }),
  })
);

await Promise.all(promiseArray)

// code steps have to return _something_
return { done: true };

Quick note: Zapier documents that calling response.throwForStatus(); is only required for core v9 or older. 10+ they call it for you.

Related