2

The commands that we want to run in sync, are a part of app.post method in app.js:

ytQueryAppJs = httpsYtGetFunc(query);
console.log("ytQueryAppJs:");
console.log(ytQueryAppJs);
  • Here, httpsYtGetFunc is a time-consuming function and the array ytQueryAppJs gets logged in before httpsYtGetFunc finishes returning value. Hence, an empty array is logged.

  • Our aim is to log ytQueryAppJs, such that it contains the required values.

(I do not know how to categorise this question. Please suggest a title you find apt.)


Here is the complete code, shall it helps anyone understand the query better.

app.js

// This is a nodeJs-expressJs application.
const express = require("express");

// https to fetch data from end-point
const https = require("https");

// body-parser to read client's submitted queryValue
const bodyParser = require("body-parser");

// This app constant is created to be able to access the methods available in 'express' package.
const app = express();

// Starting the server
app.listen(3000, function() {
  console.log("Server is running on port 3000.")
});

// 'urlencoded' helps access html data. Other data formats could be JSON etc.
// body-parser required as to exclusively define "extended: true" although this is no use to us.
app.use(bodyParser.urlencoded({
  extended: true
}));

// ejs view engine has been used to use app.js variables into the output ejs file.
app.set('view engine', 'ejs');

// Variables to store the data fetched from API endpoint.
let i = 0;

let query = "";

let ytQueryResult = "";
let ytCoverResult = "";
let ytLiveResult = "";

let ytQueryAppJs = [];

let ytCoverAppJs = [];
let ytCoverUniqueAppJs = [];

let ytLiveAppJs = [];
let ytLiveUniqueAppJs = [];

// The page to load when the browser (client) makes request to GET something from the server on "/", i.e., from the homepage.
// This GET request is made as soon as the homepage url is entered in the address bar od browser, automatically.
app.get("/", function(req, res) {
  res.sendFile(__dirname + "/index.html");
});

// https://stackoverflow.com/a/14930567/14597561
function compareAndRemove(removeFromThis, compareToThis) {
  return (removeFromThis = removeFromThis.filter(val => !compareToThis.includes(val)));
}

// Declaring variables for the function 'httpsYtGetFunc'
let apiKey = "";
let urlOfYtGetFunc = "";
let resultOfYtGetFunc = "";
let extractedResultOfYtGetFunc = [];

// This function GETs data, parses it, pushes required values in an array.
function httpsYtGetFunc(queryOfYtGetFunc) {

  apiKey = "Az...xI"
  urlOfYtGetFunc = "https://www.googleapis.com/youtube/v3/search?key=" + apiKey + "&part=snippet&q=" + queryOfYtGetFunc + "&maxResults=4&order=relevance&type=video";

  // GETting data and storing it in chunks.
  https.get(urlOfYtGetFunc, (response) => {
    const chunks = []
    response.on('data', (d) => {
      chunks.push(d)
    })

    // Parsing the chunks to jJSON
    response.on('end', () => {
      resultOfYtGetFunc = JSON.parse((Buffer.concat(chunks).toString()))
      // console.log(resultOfYtGetFunc)

      // Extracting useful data, and allocating it.
      for (i = 0; i < (resultOfYtGetFunc.items).length; i++) {
        extractedResultOfYtGetFunc[i] = resultOfYtGetFunc.items[i].id.videoId;
      }
    })
  })
  return extractedResultOfYtGetFunc;
}

app.post("/", function(req, res) {

  // Accessing the queryValue user submitted in index.js
  query = req.body.queryValue;

  // Fetcing top results related to user's query and putting them in the array.
  ytQueryAppJs = httpsYtGetFunc(query);
  console.log("ytQueryAppJs:");
  console.log(ytQueryAppJs);

  // Fetching 'cover' songs related to user's query and putting them in the array.
  if (query.includes("cover") == true) {
    ytCoverAppJs = httpsYtGetFunc(query);
    console.log("ytCoverAppJs:");
    console.log(ytCoverAppJs);

    // Removing redundant values.
    ytCoverUniqueAppJs = compareAndRemove(ytCoverAppJs, ytQueryAppJs);
    console.log("ytCoverUniqueAppJs:");
    console.log(ytCoverUniqueAppJs);
  } else {
    ytCoverAppJs = httpsYtGetFunc(query + " cover");
    console.log("ytCoverAppJs:");
    console.log(ytCoverAppJs);

    // Removing redundant values.
    ytCoverUniqueAppJs = compareAndRemove(ytCoverAppJs, ytQueryAppJs);
    console.log("ytCoverUniqueAppJs:");
    console.log(ytCoverUniqueAppJs);
  }

  // Fetching 'live performances' related to user's query and putting them in the array.
  if (query.includes("Live") == true) {
    ytLiveAppJs = httpsYtGetFunc(query);
    console.log("ytLiveAppJs:");
    console.log(ytLiveAppJs);

    // Removing redundant values.
    ytLiveUniqueAppJs = compareAndRemove(ytLiveAppJs, ytQueryAppJs);
    ytLiveUniqueAppJs = compareAndRemove(ytLiveAppJs, ytCoverAppJs);
    console.log("ytLiveUniqueAppJs:");
    console.log(ytLiveUniqueAppJs);
  } else {
    ytLiveAppJs = httpsYtGetFunc(query + " live");
    console.log("ytLiveAppJs:");
    console.log(ytLiveAppJs);

    // Removing redundant values.
    ytLiveUniqueAppJs = compareAndRemove(ytLiveAppJs, ytQueryAppJs);
    ytLiveUniqueAppJs = compareAndRemove(ytLiveAppJs, ytCoverAppJs);
    console.log("ytLiveUniqueAppJs:");
    console.log(ytLiveUniqueAppJs);
  }

  // The 'results' named EJS file is rendered and fed in response. The 'required' data is passed into it using the following variable(s).
  // res.render("results", {
  //   ytQueryEjs: ytQueryAppJs,
  //   ytCoverUniqueEjs: ytCoverUniqueAppJs,
  //   ytLiveUniqueEjs: ytLiveUniqueAppJs
  // });
  // console.log("Value to be sent for rendering: ");
  // console.log(ytQueryAppJs);
  // console.log(ytCoverUniqueEjs);
  // console.log(ytLiveUniqueEjs);

  // Emptying all the arrays.
  ytQueryAppJs.length = 0;

  ytCoverAppJs.length = 0;
  ytCoverUniqueAppJs.length = 0;

  ytLiveAppJs.length = 0;
  ytLiveUniqueAppJs.length = 0;
});

index.html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>One Music</title>
    <link rel="stylesheet" href="index.css">
  </head>
  <body onload="onPageLoad()">

    <div class="index-search-container">

      <!-- POST request to fetch data related to queryValue.  -->
      <form class="" action="/" method="post">
        <input id="queryId" type="text" name="queryValue" value="" placeholder="search">
        <button type="submit" name="button">HIT ME</button>
      </form>

    </div>

  </body>
</html>

Expected flow:

  • User submits query in index.html.
  • The values of arrays, ytQueryAppJs, ytCoverAppJs, ytCoverUniqueAppJs, ytLiveAppJs, ytLiveUniqueAppJs gets logged in the console, based on the query.

Current flow:

  • User submits query in index.js.
  • Aforementioned arrays get logged in console, but are empty.
  • User submits new query in index.html.
  • The values of arrays, ytQueryAppJs, ytCoverAppJs, ytLiveAppJs, gets logged in the console, based on the previous query.
  • These two arrays are also logged in but are still empty: ytCoverUniqueAppJs, ytLiveUniqueAppJs.

Note: I am a beginner. Shall the question requires better tags, please edit.

Varun
  • 73
  • 1
  • 10
  • Alright, buddy. I'll modify the question. – Varun May 30 '21 at 02:39
  • My motive for asking a question this way, was to understand the concept by going through the implementation (had someone answered with one.) I'm an absolute beginner, new to the community. I read some articles but I found them hard to implement. – Varun May 30 '21 at 02:50
  • Try debugging by console logging `req.body.queryValue` at the beginning of your `app.post` callback – Binary May 30 '21 at 02:58
  • Okay. I tried, and logging in `req.body.queryValue`, indeed logs the input query value. – Varun May 30 '21 at 03:09
  • I tried modifying the question. Could you please suggest improvements? – Varun May 30 '21 at 03:12
  • 1
    Your question is fine as-is. It no longer reads as a request for free work, as Simon so bluntly put. I don't believe you were ever asking for such, but there's always the issue of appearance, since not a lot of people put as much effort into their questions as you have. I've upvoted your question for the effort you've put into editing it in response to the feedback you've gotten. – Patrick Roberts May 30 '21 at 03:15
  • @PatrickRoberts Thank you so much, sir. I highly appreciate it. :) – Varun May 30 '21 at 03:16
  • 1
    You might want to take a look at [How to return the response from an asynchronous call?](https://stackoverflow.com/q/14220321) – Patrick Roberts May 30 '21 at 03:29
  • @PatrickRoberts Thank you for looking it up. I tried the method "2. Restructure Code" in the [answer](https://stackoverflow.com/a/16825593/14597561), but it ended up the same as aforementioned 'Current Flow'. Although, this approach would have lead to a very nested and dirty code, had it worked. It didn't give any error, so I'm expecting I did it right. It's the simple 'callback function' way, if I'm not wrong. – Varun May 30 '21 at 06:40
  • 1
    @PatrickRoberts [This](https://stackoverflow.com/q/67758853/14597561) is what I coded. I find myself pretty close. Could you please take a look? – Varun May 30 '21 at 07:40

0 Answers0