Как сохранить соединение от angular до nodejs - PullRequest
0 голосов
/ 10 января 2020

Я создаю приложение nodejs (10.16.0) и angular (8.0.3).

Один из модулей этого приложения предназначен для извлечения данных из базы данных путем выполнения довольно большой запрос (только для чтения, 80 строк с некоторыми внутренними объединениями и несколькими условиями), в конце, в зависимости от отправляемых параметров, этот процесс может извлечь от 0 до более 600 000 строк (или даже больше), поэтому запрос выполнение может занять от 1 секунды до даже 4 минут.

Процесс следующий:

  1. Пользователь вставляет (из внешнего интерфейса) несколько параметров.
  2. Пользователь нажимает на кнопка «Генерировать».
  3. Angular создает JSON с данными, необходимыми для формирования запроса, и отправляет его на сервер Nodejs.
  4. Nodejs получает JSON и формирует его запрос (здесь время начинает отсчитываться, весь процесс может занять от 0 до 240 секунд).
  5. Nodejs запрашивает у сервера DB2 результат запроса (этот подпроцесс занимает больше времени, даже несколько минут)
  6. Nodejs получает результат.
  7. * 1 059 * очищает результат (0 - 5 секунд в зависимости от длины массива).
  8. Nodejs возвращает очищенный список в angular.
  9. Angular создает файл с очищенным списком (еще 0 - 5 секунд).
  10. Загрузка файла.

Мой angular запрос (функция вызывается после нажатия на кнопку отправки):

  // User input is the JSON that contains parameters
  getReportData(userInput: JSON): Observable<MyInterface> {
    return this.httpClient.post<MyInterface>(`${this.MyURL}/generateReport`, { userInput })
      .pipe(
        catchError(e => throwError(new Error("No Cost Types found" + e.message))));
  }

Мой nodejs ответ конечной точки:

router.post('/generateReport', async (req, res, next) => {
    try {
        // ** Here it is when the time starts to count**
        const result = await dataRetriever.getData(req.body.userInput);
        if (result instanceof Error) next(createError(result, 400));
        else res.send(result);
    } catch (error) {
        next(createError(error, 400));
    }
});

Функция извлечения данных:

async function getData(userInput) {
    const query = queryGenerator.getCQRDataRetrieveQuery(userInput);
    // This await is the process that can take several minutes
    const data = await queryExecutor.executeStatement(query);
    if (data.length >= 1) {
        const result = sanitizeDBResults(data);
        return result;
    } else {
        // In case no rows were found
        return [];
    }
}

Проблема заключается в том, что когда angular ожидает ответа после нажатия кнопки «Создать», он выключается обрыв соединения через 60 секунд ожидания (что меньше времени, чем в уже рассмотренных примерах).

Это сообщение, отображаемое на консоли chrome после 60 секунд ожидания:

zone.js:3372 POST https://*myURL*/generateReport 504 (Gateway Time-out)

Я слышал о заголовке с именем «keep alive» или о реализации веб-сокетов для «heartbeat» от nodejs до angular, чтобы клиентская часть знала, что соединение все еще живо, но это правильный подход ? Какое еще решение может быть простым и эффективным?

Так что мне нужно реализовать способ удержания Angular ответа на запрос более 60 секунд, результаты запроса могут занять 4 минуты или даже больше, если это необходимо.

Есть идеи по этому поводу?

1 Ответ

1 голос
/ 10 января 2020

Я особенно не думаю, что часть сборки файла с JS необходима. Вы можете просто добавить заголовок Content-Disposition поверх Content-Type и загрузить его напрямую. Пример:

Content-Disposition: attachment; filename = "report.txt"

Но если проблема остается в тайм-ауте, вы можете указать это Express:

Глобально:

const server = app.listen();
server.setTimeout(600000);

Или просто для уточнения c route:

app.post('/xxx', (req, res) => {
    req.setTimeout(600000);
});

И поскольку это довольно большой файл, я рекомендую вам взглянуть на: Отправлять данные кусками с помощью nodejs

...