twiliotwilio-programmable-chat

How do I make my for await loop do everything within its body before moving on to the next line of code in twilio serverless functions?


I have been working on this problem for a couple of days now, and feel like I'm extremely close to solving the issue. I need to cycle through an object and send a text message to each record in the object before moving on to the next line of code. The code to send works when isolated locally. But I'm having trouble getting it to work in Twilio Functions. All my code appears to work, but the text messages are not sent.

    for await (const contact of allItems) {
      client.messages
      .create({
      body: "Hey " + contact.name + "!" + " " + message,
      messagingServiceSid: messaging_service,
      to: contact.key
      });
    };
    
  // End Send Message to Each Contact

I've attached the portion of code I believe I'm having issues with.

What I want to do, is for this piece of code to run completely before moving on to the next few lines and invoking a callback.

Any idea how I could do something like this?


Solution

  • Twilio developer evangelist here.

    The issue here is that you are not awaiting the actual result of the asynchronous call. Locally, that doesn't matter, but within Twilio Functions once you call the callback function all asynchronous calls that have started are terminated.

    To create a loop that makes asynchronous requests and waits for them all to complete you will want to use Promise.all in conjunction with map. In your example, it should look like this:

    function SendMessages(allItems, message, client, messagingService) {
      const apiRequests = allItems.map((contact) => {
        let usersName = contact.name;
        return client.messages.create({
          body: `Hey ${usersName}! ${message}`,
          messagingServiceSid: messagingService,
          to: contact.key,
        });
      })
      return Promise.all(apiRequests);
    }
    

    In this function we map over the list contacts returning the promise that is created when we try to send a message. The variable apiRequests becomes an array of promises that represent the requests to the API. We can then use this array of promises in Promise.all. Promise.all will only resolve once all the promises it is passed have resolved (or if a promise rejects).

    I recommend you read my answer to your previous question as that brings up some further issues that you might have with this.