【发布时间】:2022-10-19 00:18:27
【问题描述】:
Express.js 为 Remix 应用程序提供服务。服务器端代码在启动时设置了几个计时器,这些计时器每隔一段时间就会执行各种后台作业,其中一个会检查远程 Jenkins 构建是否完成。如果是这样,它会将多个大型 PDF 从一个网络路径复制到另一个网络路径(都在 GSA 上)。
一个函数创建了一系列链式 glob+copyFile 承诺:
import { copyFile } from 'node:fs/promises';
import { promisify } from "util";
import glob from "glob";
...
async function getFiles() {
let result: Promise<void>[] = [];
let globPromise = promisify(glob);
for (let wildcard of wildcards) { // lots of file wildcards here
result.push(globPromise(wildcard).then(
(files: string[]) => {
if (files.length < 1) {
// do error stuff
} else {
for (let srcFile of files) {
let tgtFile = tgtDir + basename(srcFile);
return copyFile(srcFile, tgtFile);
}
}
},
(reason: any) => {
// do error stuff
}));
}
return result;
}
另一个异步函数获取该数组并对其执行 Promise.allSettled :
copyPromises = await getFiles();
console.log("CALLING ALLSETTLED.THEN()...");
return Promise.allSettled(copyPromises).then(
(results) => {
console.log("ALLSETTLED COMPLETE...");
在“CALLING”和“COMPLETE”消息之间,可能需要几分钟的时间,服务器不再响应浏览器请求,超时。
但是,在此期间,仍然可以看到我的其他活动后端计时器在服务器控制台日志中运行并正常完成(出于测试目的,我每 5 秒运行一次,并且在这些文件副本爬行时它一遍又一遍地运行非常平稳沿着)。
所以它并没有阻止整个服务器,它似乎只是阻止浏览器请求被处理。并且一旦在日志中弹出“COMPLETE”消息,浏览器请求就会再次正常处理。
Express 启动脚本基本上只是为 Remix 执行此操作:
const { createRequestHandler } = require("@remix-run/express");
...
app.all(
"*",
createRequestHandler({
build: require(BUILD_DIR),
mode: process.env.NODE_ENV,
})
);
这是怎么回事,我该如何解决?
【问题讨论】:
-
我会使用
child-process在另一个线程中运行任务 -
哇,好诡异! fs.copyFile(srcFile, tgtFile) 将服务器连接到 HTTP 请求,但使用 child_process.exec("copy " + srcFile + " " + tgtFile) 根本不会。浏览器请求在浏览所有这些副本时会立即处理!后者依赖于操作系统,但我当然可以接受,因为它处理问题的方式非常简单(而且很好)。我仍然不明白的是……鉴于据报道 Node“非常擅长异步 I/O”,为什么 async copyFile 会有效地阻塞服务器?
-
裸体在一个线程中运行。它适用于多个短期任务。如果某些操作需要很长时间,它会阻塞。
-
我不知道混音,
createRequestHandler是做什么的?它是否尝试从文件系统提供文件? -
"它复制了几个大的 PDF“ - 我们在这里谈论多少个文件?
标签: javascript express remix.run