如何保持从 angular 到 nodejs 的连接

How to keep alive a connection from angular to nodejs

我正在制作一个 nodejs(10.16.0) 和 angular(8.0.3) 应用程序。

这个应用程序的一个模块旨在通过执行一个非常大的查询(read-only 目的,80 行带有一些内部连接和几个条件)从数据库中检索数据,最后,取决于在发送的参数上,这个过程可以检索 0 到超过 600,000 行(甚至更多),因此查询执行可能需要 1 秒甚至 4 分钟。

下一个进程:

  1. 用户插入(从前端)几个参数。
  2. 用户点击生成按钮。
  3. Angular 使用形成查询所需的数据构建一个 JSON 并将其发送到 Nodejs 服务器。
  4. Nodejs收到JSON并形成这个查询(这里开始计时,整个过程可能需要0-240秒)。
  5. Nodejs 向 DB2 服务器询问查询结果(这是 sub-process 需要更长的时间,甚至几分钟)
  6. Nodejs 获取结果。
  7. Nodejs 清理结果(0 - 5 秒,具体取决于数组长度)。
  8. Nodejs returns 清理列表到 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 在单击 'generate' 按钮后等待响应时,它会在等待 60 秒后关闭连接(这比已经看到的示例的时间少)。

这是等待 60 秒后 chrome 控制台上显示的消息:

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

我听说过一个叫做 'keep alive' 的 header 或实现网络套接字到 'heartbeat' 从 nodejs 到 angular 所以前端知道连接仍然存在,但是这些正确的方法?还有什么简单有效的解决方案?

所以我需要实现的是一种让 Angular 听到响应的时间超过 60 秒的方法,如果需要,查询结果可能需要 4 分钟甚至更长时间。

对此有什么想法吗?

我特别觉得用JS拼装文件的部分没必要。您可以简单地在 Content-Type 之上添加 Content-Disposition header 并直接下载。示例:

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

但是如果超时问题依旧,你可以指定给Express:

全球:

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

或仅针对特定路线:

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

而且文件比较大,建议大家看看:Send data in chunks with nodejs