如何解决如何在没有 http 服务器的情况下在内部使用 koa 应用回调?
A 有一个基于 koa 的 js 应用程序并致力于服务器端渲染。在应用程序的其余部分中,我正在从运行 SSR 的同一台服务器加载一些脚本。虽然加载可以通过标准的 HTTP 请求,但它会不必要地慢。所以我想简单地调用 koa 提供的 app.callback()
将请求解析为请求文件的字符串。对于 SSR,我使用 jsdom,它加载文件并作为浏览器处理它们。
问题是我无法得到结果,resp。 “服务器响应”的主体。我试图模拟服务器请求和服务器响应,然后只是读取套接字。我不确定这是否是最好的方法,但它似乎可行。但是,当我运行该应用程序时,我只得到两个块 - 用于大型前端文件的字符串缓冲区。第一个块是标题。其次是代码的一部分,但只有 64kB。我无法获得下一块。似乎模拟的可写流停止了。也许它被塞住了,但我不确定为什么以及是否完全。
如果我尝试加载小于 64kB 的脚本,请求将被正确解析并且流已完成。
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { Writable } = require("stream");
const http = require("http");
const fetch = async (url,options) => {
const response = [];
let finishedReolve;
const finished = new Promise(resolve => (finishedReolve = resolve));
const socket = new Writable({
write: (data,encoding,cb) => {
console.log("write",data);
// outputs 2 times - 1. headers,2. 64kB part of requested code
response.push(data);
cb();
return true;
},destroy(err,cb) {
// Never gets called
console.log("destroy",err);
cb();
finishedReolve();
},final(cb) {
// Never gets called
console.log("final");
cb();
finishedReolve();
},});
const req = new http.IncomingMessage(socket);
req.method = "GET";
const parsedURL = new URL(url);
req.url = parsedURL.pathname;
const res = new http.ServerResponse(req);
res.assignSocket(req.socket);
res.on("prefinish",() => {
// Never gets called
finishedReolve();
});
await this.callback()(req,res);
await finished;
return response[0];
};
class CustomresourceLoader extends jsdom.ResourceLoader {
fetch(url,options) {
return fetch(url,options);
}
}
const dom = await JSDOM.fromFile(index_html_path,{
url: domain + ctx.req.url,runScripts: "dangerously",resources: new CustomresourceLoader(),});
流有什么问题?有没有其他方法可以使用 app.callback()
来获取 koa 应用程序的输出?
解决方法
问题是,可读流正在发送 64kB 的块,但我的可写流将 highWaterMark
设置为默认 16kB。这(可能)导致可读流在写入更多可写可以处理的数据后等待耗尽,这是在第一个 64kB 块之后。
解决方案是将 highWaterMark
设置为大于可读流的值,因此例如
highWaterMark: 1024 * 64 * 2,
所以套接字看起来像这样:
const socket = new Writable({
highWaterMark: 1024 * 64 * 2,write: (data,encoding,cb) => {
response.push(data);
cb();
return true;
},destroy(err,cb) {
console.log("destroy",err);
cb();
finishedReolve();
},final(cb) {
console.log("final");
cb();
finishedReolve();
},});
还要结束,我需要听那个奇怪的事件 prefinish
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。