Создание видео с помощью JavaScript 3

Со времени моего последнего сообщения в блоге я исправил несколько сохраняющихся ошибок и продолжил работу с ffmpeg. Приложение будет принимать пользовательский ввод для url вопросов stackoverflow и url видео на youtube и создавать рассказывающий тикток, подобный этому проекту. Сначала я кратко объясню некоторые из этих ошибок и как я их исправил, а затем объясню первый вызов функции, с которой все начинается.

Внесенные изменения и исправленные ошибки

Ошибки, которые я в итоге исправил, на самом деле были частью функции makeApiCall(), о которой я расскажу позже в этом посте. У меня были проблемы с асинхронностью при получении данных из API stackoverflow. Я впервые делал запросы на выборку в Node, и забыл добавить await перед выборкой данных. Это не всегда было проблемой, только иногда функции, которые полагались на ответ, выдавали ошибку. Поскольку обычно это происходило так редко, я подумал, что это проблема с API и количеством запросов. Я решил посмотреть на функцию поближе и заметил, что в обоих вызовах API отсутствует await, и с тех пор ошибка не возникала.

Я отошел от этого проекта, чтобы немного поработать над своим портфолио. Я не достиг большого прогресса с момента моего последнего сообщения, но все же кое-что сделал. Функция, которая добавляет mp3-звук из API Googles text-to-speech к скриншотам, иногда работает, но у меня все еще есть несколько постоянных ошибок, которые я устраняю. Даже просто при написании этого сообщения и просмотре ошибок у меня появилось еще несколько идей по устранению проблем, и я надеюсь, что к следующему сообщению все будет работать немного лучше.

Файл api-call.js

api-call.js — это первая функция, которая вызывается внутри startVideoEdit() после того, как пользователь передал свои данные. Функция принимает url вопроса и несколько глобальных переменных, которые она использует для хранения частей ответа.

Файл импортирует три модуля

import fetch from "node-fetch";
import chalk from "chalk";
import { parseText } from "./parse-text.js";
Вход в полноэкранный режим Выход из полноэкранного режима

Node Fetch довольно прост, и я уже объяснял, что такое Chalk и как он используется в предыдущих постах. Parse text get вызывается из этого файла для преобразования HTML-строк, возвращаемых из вызовов API, в обычный текст.

Первым шагом будет извлечение ID вопроса из url, переданного в функцию, так как это единственная часть url, которая нам действительно нужна.

const url = questionURL;
const questionId = url
  .match(//(d+)+[/]?/g)
  .map((id) => id.replace(///g, ""));
Вход в полноэкранный режим Выход из полноэкранного режима

Затем мы можем интерполировать questionId в два разных url, один для получения данных о вопросах, а другой для ответов.

const qURL = `https://api.stackexchange.com/2.3/questions/${questionId}?order=desc&sort=activity&site=stackoverflow&filter=withbody`;
const aURL = `https://api.stackexchange.com/2.3/questions/${questionId}/answers?order=desc&sort=activity&site=stackoverflow&filter=withbody`;
Вход в полноэкранный режим Выход из полноэкранного режима

Затем мы можем использовать qURL для запроса API.

const getQuestionData = async () => {
  await fetch(qURL)
    .then((r) => r.json())
    .then((data) => handleQuestionResponse(data));
};
Войти в полноэкранный режим Выход из полноэкранного режима

Вот здесь и проявляется та ошибка, о которой я говорил ранее. Теперь я знаю, что в Node всегда нужно await fetches. Затем я вызываю вспомогательную функцию handleQuestionResponse() и передаю ей JSON-данные ответа.

Во-первых, если на вопрос нет ответа, ничего из этого не сработает. Если на вопрос был дан ответ, я сохраняю количество ответов, html-строку тела вопроса, а также html-строку заголовка вопроса.

async function handleQuestionResponse(data) {
  if (data.items[0].is_answered !== true) {
    console.log(
      "Sorry, this question isn't answered yet. Try again with another question."
    );
    questionDataObj.isAnswered = data.items[0].is_answered;
  } else {
    questionDataObj.answerCount = data.items[0].answer_count;
    questionDataObj.htmlString = [data.items[0].body];
    questionDataObj.title = [data.items[0].title];
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Затем aURL используется для запроса к API

const getAnswerData = async () => {
  await fetch(aURL)
    .then((r) => r.json())
    .then((data) => handleAnswerResponse(data));
};
Войти в полноэкранный режим Выход из полноэкранного режима

Опять же, именно здесь ошибка await вызывала у меня проблемы. Опять же, я использую вспомогательную функцию, которая принимает JSON-данные ответов.

Сначала я отображаю каждый объект в JSON, сохраняя его ID в массив. Затем я снова работаю с каждым объектом, сохраняя HTML-строки в массив. То же самое я делаю для интерполяции ID в строку, чтобы дать каждому ответу название, которое впоследствии можно будет использовать в файлах. Затем я трижды вызываю функцию parseText(). Первый вызов используется для получения обычного текста для ответов, второй — для тела вопроса и последний — для заголовка. Глядя на эту функцию сейчас, я не уверен, почему parseText() находится внутри handleAnswerResponse(), а не вызывается снаружи в главной функции, экспортируемой из файла. Возможно, я еще повожусь с этим и перенесу вызовы этих функций за пределы этой вспомогательной функции.

async function handleAnswerResponse(data) {
  let answersIds = data.items.map((el) => el.answer_id);
  questionDataObj.answerIds = answersIds;
  let htmlAns = data.items.map((el) => el.body);
  let titles = data.items.map((el) => `answer${el.answer_id}`);
  titles.forEach((el) => fileNames.push(el));
  // parse answers
  await parseText(htmlAns, plainTextStrings, questionDataObj);
  // parse question body
  await parseText(
    questionDataObj.htmlString,
    plainTextStrings,
    questionDataObj,
    false
  );
  // parse question title
  await parseText(
    questionDataObj.title,
    plainTextStrings,
    questionDataObj,
    true
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Это все, что есть в этом файле, кроме вызова getAnswerData() и getQuestionData(). Конечно, здесь есть куда совершенствоваться, и я планирую кое-что из этого изменить к следующему разу, когда буду писать об этом проекте. Если у вас есть какие-либо вопросы, я постараюсь ответить на них в комментариях. Спасибо за чтение и не стесняйтесь проверять некоторые из моих других постов здесь на dev.to

Оцените статью
devanswers.ru
Добавить комментарий