Home > Mobile >  Do Axios request with SQL array
Do Axios request with SQL array

Time:03-15

I'm trying to query mySQL database inside Express route, get an array called "subjects", then run axios request with the array. Then I want to display the responses on EJS.

Such as,

// for-each "subject", 
    var url = `http://news.com/${subject}`
    const articles_get =await axios.get(url)
    res.render('news',{articles:articles_get.data.articles})

I tried so many things, I keep getting errors about "async/await must be at the top level" and "HEADERS ALREADY SENT". I tried following other examples on SO but none have worked. I think I'm missing some idea. Please any help is appreciated!

Here's my current code that says "SyntaxError: await is only valid in async functions and the top level bodies of modules" I tried to move the function out of the route, then call it inside the route, but it just never returned anything.

app.get("/mySubjects", (req, res) => {
  var subjects = [];
  var username = req.body["username"];

  connection.query(
    "SELECT * FROM mySubjects WHERE username = ?",
    [username],
    async function (error, results, fields) {
      if (error) {
        throw error;
      }
      if (results.length > 0) {
        results.forEach((result) => {
          subjects.push(result.subject);
        });

        subjects.forEach((subject) => {
          //call NEWS API FOR EACH SUBJECT
          try {
            var url = `https://newsapi.org/v2/top-headlines/sources?category=${subject}apiKey=c7777777777777`;

            const news_get = await axios.get(url);
            res.render("news", { articles: news_get.data.articles });
          } catch (error) {
            if (error.response) {
              console.log(error);
            }
          }
        });
      } else {
        res.status(401).send({ message: "Nothing is here." });
      }
    }
  );
});

CodePudding user response:

You can only call res.render() once as it will render your template and respond to the client. What you need to do is collect all your data first, then render your template.

For example

if (results.length > 0) {
  // using Promise.allSettled so it doesn't bail at the first failed request
  const allResults = await Promise.allSettled(
    results.map(async ({ subject }) => {
      const { data: { articles } } = await axios.get("https://newsapi.org/v2/top-headlines/sources", {
        params: { // params is the easy way to pass query parameters
          category: subject,
          apiKey: "c7777777777777",
        }
      });
      return { subject, articles };
    })
  );

  // Extract all the successful responses
  const allArticles = allResults
    .filter(({ status }) => status === "fulfilled")
    .map(({ value }) => value);

  // render your template
  res.render("news", { allArticles });

  // optionally log the failed requests
  allResults
    .filter(({ status }) => status === "rejected")
    .forEach(({ reason }) => {
      console.error(reason.response?.data ?? reason.message)
    })
} else {
  // 401 is for Unauthorized, use 404 for Not Found
  res.status(404).send({ message: "Nothing is here." });
}

This will render your news template, passing a property named allArticles which is an array of objects with subject and articles properties.

CodePudding user response:

You should not send a response inside forEach since it has not done iterating.

The example below will return all response.data as an array and make sure you handle them accordingly in ejs file.

app.get('/mySubjects', (req, res) => {
  const username = req.body['username'];

  connection.query(
    'SELECT * FROM mySubjects WHERE username = ?',
    [username],
    function (error, results, fields) {
      if (error) throw error;

      if (results.length > 0) {
        const requests = results.map(({ subject }) =>
          axios.get(
            `https://newsapi.org/v2/top-headlines/sources?category=${subject}apiKey=c7777777777777`,
          ),
        );
        Promise.all(requests)
          .then((news) => {
            res.render('news', { news });
          })
          .catch((err) => {
            // Handle error
            console.log(err.message);
          });
      } else {
        res.status(401).send({ message: 'Nothing is here.' });
      }
    },
  );
});
  • Related