What I’m trying to do:
- Incoming call from user would trigger a Digits
Gather
(No problem) - After receiving the Digits,
Say
something to the user Play
music while fetching phone number from an API usingasync/await
Dial
said phone number from API’s response.
My Code:
gather-extension.js
(Gather and retry both work, thus not providing retry js)
exports.handler = async (context, event, callback) => {
const retryMax = 2;
const twiml = new Twilio.twiml.VoiceResponse();
const gather = twiml.gather({
action: `./fetch-driver-phone`,
method: 'GET',
timeout: 2
});
gather.say('Thanks for calling');
//retry
twiml.redirect(`./retry-gather-ext?retry=1&retry_max=${retryMax}`);
return callback(null, twiml);
}
fetch-driver-phone.js
(This is where the problem is)
exports.handler = async (context, event, callback) => {
const twiml = new Twilio.twiml.VoiceResponse();
const callerPhoneNumber = event.From;
const extension = event.Digits;
console.log('Caller Phone Number:', callerPhoneNumber);
if (extension == null) {
//handle error
}
twiml.say("Please wait while we connect you");
twiml.play("http://com.twilio.sounds.music.s3.amazonaws.com/MARKOVICHAMP-Borghestral.mp3");
try {
console.log("Calling API");
const result = await fetchDriver(extension, twiml)
console.log(result);
twiml.dial().number(result);
callback(null, twiml);
} catch(error) {
console.error(error);
twiml.say('We are unable to process your request at this time.');
twiml.hangup();
callback(error);
}
}
const fetchDriver = async (code) => {
console.log('Extension Digits:', code);
return new Promise((resolve) => {
setTimeout(() => {
resolve('phone number');
}, 5000);
});
}
What is expected:
I expect the Say
and Play
to execute before the await statement. Then Dial
is called after the response is fetched.
What is happening:
Say
and Play
are not triggered UNTIL await’s 5000ms is over, then Dial
is flat-out ignored. I have tried using the actual API, and I got the same result.
When I use chatGPT or Twilio support AI. Both Gave me the solution of adding callback(null, twmil)
right after Play
. This indeed fixed the timing issue, however, it resulted in Dial
never being called.
Then both AI’s suggested adding an additional VoiceResponse
to be used after the first callback(null, twmil)
. This results in the response console.log showing up at the beginning of the 2nd call. The first call would still be stuck in the Play
music.
I also tried using Enqueue
, but got the same result.
I ran out of options and things to try. Thus I’m seeking help here. Thanks for any input!
0
The behavior you see is the correct one, as the TwiML (returned by the function) won’t be available until the function completes. Therefore, Twilio won’t be able to know about the say/play widgets until they are unnecessary.
The solution is to split this into two functions:
- The first one basically does what ChatGPT suggested. It returns the say and play widgets, so the users immediately start to hear the message. But it also triggers the second function
- The second one awaits
fetchDriver
and then modifies the call in progress. You will then override the TwiML of the call with the new stage of the conversation.
1