0

I am fairly new to the whole asynchronous world. Had to start for implementing Twilio video call through node.

I have been trying to call this server side function which then calls another asynchronous function that returns promise. The then portion works fine and I am able to see output in console. But when I try to call another function in then which has an ajax call to the main application to save some data in database.

Neither am I able to send the returned value in response.send() nor am I able to call a function in then.

Please help!

Server Side - index.js

'use strict';

/**
 * Load Twilio configuration from .env config file - the following environment
 * variables should be set:
 * process.env.TWILIO_ACCOUNT_SID
 * process.env.TWILIO_API_KEY
 * process.env.TWILIO_API_SECRET
 */
require('dotenv').load();

const express = require('express');
const http = require('http');
const path = require('path');
const { jwt: { AccessToken } } = require('twilio');
const Twilio = require('twilio');
const jquery = require( 'jQuery');
const cors = require('cors');

const VideoGrant = AccessToken.VideoGrant;

// Max. period that a Participant is allowed to be in a Room (currently 14400 seconds or 4 hours)
const MAX_ALLOWED_SESSION_DURATION = 14400;

// Create Express webapp.
const app = express();

// Set up the path for the HealthAssure.
const startPath = path.join(__dirname, '../HAVideoConsultation/public');
app.use('/HAVideoConsultation', express.static(startPath));

/**
 * Default to the application.
 */
app.get('/', (request, response) => {
  response.redirect('/HAVideoConsultation');
});

/**
 * Generate an Access Token for a chat application user - it generates a random
 * username for the client requesting a token, and takes a device ID as a query
 * parameter.
 */
app.get('/token', function(request, response) {
  const { identity } = request.query;

  // Create an access token which we will sign and return to the client,
  // containing the grant we just created.
  const token = new AccessToken(
    process.env.TWILIO_ACCOUNT_SID,
    process.env.TWILIO_API_KEY,
    process.env.TWILIO_API_SECRET,
    { ttl: MAX_ALLOWED_SESSION_DURATION }
  );

  // Assign the generated identity to the token.
  token.identity = identity;

  // Grant the access token Twilio Video capabilities.
  const grant = new VideoGrant();
  token.addGrant(grant);

  // Serialize the token to a JWT string.
  response.send(token.toJwt());
});

function pushCompositionId(compositionId){
    console.log(compositionId);
    jquery.ajax({            
        url:'http://localhost:58674/ABC/XYZ',
        type:'GET',
        data: {CompositionId:compositionId},
        cors: true,
        success:function(result){ 
            Console.log('Composition Id pushed successfully.');
        },
        error:function(err){
            console.log(err);
            return false;
        }            
    });
} 


app.get('/Composition',function(request,response){
    const client = new Twilio(process.env.TWILIO_API_KEY,process.env.TWILIO_API_SECRET, {accountSid: process.env.TWILIO_ACCOUNT_SID}); 
    const cid = null;
    client.video.compositions
        .create({
        roomSid: request.query.roomSid,
        audioSources: '*',
        videoLayout: {
          grid : {  
            video_sources: ['*']
          }
        },     
        format: 'mp4'
      }).then(composition =>{      
    console.log("Created Composition with SID=" + composition.sid); // This works properly
    cid=composition.sid;
    // pushCompositionId(composition.sid); // I want to call this function here
  });
  response.send(cid); // This does not return proper value
});

// Create http server and run it.
const server = http.createServer(app);
const port = process.env.PORT || 3000;
server.listen(port, function() {
  console.log('Express server running on *:' + port);
});

Client side

async function GenerateCompositionId(roomsid){
const compositionid = await fetch(`/Composition?roomSid=${roomsid}`);  
}

Server Side function I want to call in then after Composition.sid is generated. If I put this in a try block it gives me error jquery.ajax is not a function. I have included it require and another ajax function on client side is working fine. Why does this not?

function pushCompositionId(compositionId){
    jquery.ajax({            
        url:'http://localhost:58674/ABC/XYZ',
        type:'GET',
        data: {CompositionId:compositionId},
        cors: true,
        success:function(result){ 
            Console.log('Composition Id pushed successfully.');
        },
        error:function(err){
            console.log(err);
            return false;
        }            
    });
} 
  • Can you include the full ServerSide file? in order to understand where are declared the other functiions. jQuery is included in your ServerSide? – MadPapo Jul 14 '20 at 14:21
  • I have edited and included the whole server side code – Mudra Rastogi Jul 14 '20 at 14:29
  • Are you sure that the function iinside pushCompisitionId is not called? Or the problem is that it is executed after you send response to the client? – MadPapo Jul 14 '20 at 14:50
  • The function is called. If I remove the ajax portion and simply put a console.log(compositionid) then I see correct output in console. I think the problem is the timing of sending response to client. It does not wait for then to resolve. – Mudra Rastogi Jul 14 '20 at 14:56

1 Answers1

-1

In order to send the response when the async calls are done the server-side must be:

var jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { window } = new JSDOM();
const { document } = (new JSDOM('')).window;
global.document = document;

var $ = jQuery = require('jquery')(window);

function pushCompositionId(compositionId,response){
    console.log(compositionId);
    jquery.ajax({            
        url:'http://localhost:58674/ABC/XYZ',
        type:'GET',
        data: {CompositionId:compositionId},
        cors: true,
        success:function(result){ 
            Console.log('Composition Id pushed successfully.');
            response.send(cid); // This does not return proper value
        },
        error:function(err){
            console.log(err);
            response.send(false);
        }            
    });
} 


app.get('/Composition',function(request,response){
    const client = new Twilio(process.env.TWILIO_API_KEY,process.env.TWILIO_API_SECRET, {accountSid: process.env.TWILIO_ACCOUNT_SID}); 
    const cid = null;
    client.video.compositions
        .create({
        roomSid: request.query.roomSid,
        audioSources: '*',
        videoLayout: {
          grid : {  
            video_sources: ['*']
          }
        },     
        format: 'mp4'
      }).then(composition =>{      
        console.log("Created Composition with SID=" + composition.sid); // This works properly
        cid=composition.sid;
        pushCompositionId(composition.sid,response); // I want to call this function here
      });
});

Otherwise you can use await/async to return a sync-like result

MadPapo
  • 495
  • 4
  • 13
  • Why downvoting? – MadPapo Jul 14 '20 at 16:17
  • I didn't downvote. Btw I will check your solution. Until now I was explicitly writing response.send – Mudra Rastogi Jul 14 '20 at 16:23
  • I'm successfully being redirect to pushCompositionId now. But ajax is still not executed properly. When I enclosed it in a try catch block, I received this error -TypeError: jquery.ajax is not a function. I have included jQuery in my file. I don't understand. – Mudra Rastogi Jul 14 '20 at 17:04
  • jQuery cannot be used like in the client-side (you can manage requests with native Net module in NodeJS). Btw, I correct my answer to include the correct jQuery import (you wiiill require other modules and to emulate the browser window to let it works) – MadPapo Jul 14 '20 at 17:09
  • Yea I just read in some other thread. Used jsdom and now it is working. Thank you for your help! :) – Mudra Rastogi Jul 14 '20 at 17:47